From 5ab433a2ec566c19f6ffc0760fac7b179eb27083 Mon Sep 17 00:00:00 2001 From: evitayan Date: Wed, 6 Feb 2019 20:00:36 -0800 Subject: ChildSession skeleton for first Child negotiation This commit: - Create ChildSessionStateMachine skeleton to support negotiating first Child SA - Leave TODO in IkeSaPayload to validate proposal accoding to who is SA initiator Bug: 122736232 Test: Test: FrameworksIkeTests ChildSessionStateMachineTest Change-Id: I89d70fce97c42e829d5a9381e84523f11b0afd92 --- .../ike/ikev2/ChildSessionStateMachineTest.java | 138 +++++++++++++++++++++ .../ike/ikev2/IkeSessionStateMachineTest.java | 23 +++- .../com/android/ike/ikev2/message/TestUtils.java | 23 ++-- 3 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java (limited to 'tests/iketests/src/java/com/android') diff --git a/tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java b/tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java new file mode 100644 index 00000000..f16ada74 --- /dev/null +++ b/tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java @@ -0,0 +1,138 @@ +/* + * 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.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.os.test.TestLooper; + +import com.android.ike.ikev2.IkeSessionStateMachine.IChildSessionCallback; +import com.android.ike.ikev2.SaRecord.ChildSaRecord; +import com.android.ike.ikev2.SaRecord.ISaRecordHelper; +import com.android.ike.ikev2.SaRecord.SaRecordHelper; +import com.android.ike.ikev2.exceptions.IkeException; +import com.android.ike.ikev2.message.IkePayload; +import com.android.ike.ikev2.message.TestUtils; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +public final class ChildSessionStateMachineTest { + private static final String IKE_AUTH_REQ_SA_PAYLOAD = + "2c00002c00000028010304032ad4c0a20300000c0100000c800e0080" + + "03000008030000020000000805000000"; + private static final String IKE_AUTH_RESP_SA_PAYLOAD = + "2c00002c0000002801030403cae7019f0300000c0100000c800e0080" + + "03000008030000020000000805000000"; + + private static final String CURRENT_CHILD_SA_SPI_IN = "2ad4c0a2"; + private static final String CURRENT_CHILD_SA_SPI_OUT = "cae7019f"; + + private TestLooper mLooper; + private ChildSessionStateMachine mChildSessionStateMachine; + + private List mAuthReqSaNegoPayloads = new LinkedList<>(); + private List mAuthRespSaNegoPayloads = new LinkedList<>(); + + private ChildSaRecord mSpyCurrentChildSaRecord; + + private ISaRecordHelper mMockSaRecordHelper; + private IChildSessionCallback mMockChildSessionCallback; + private ChildSessionOptions mMockChildSessionOptions; + + public ChildSessionStateMachineTest() { + mMockSaRecordHelper = mock(SaRecord.ISaRecordHelper.class); + mMockChildSessionCallback = mock(IChildSessionCallback.class); + mMockChildSessionOptions = mock(ChildSessionOptions.class); + } + + @Before + public void setup() throws Exception { + // Setup thread and looper + mLooper = new TestLooper(); + mChildSessionStateMachine = + new ChildSessionStateMachine( + "ChildSessionStateMachine", mLooper.getLooper(), mMockChildSessionOptions); + mChildSessionStateMachine.setDbg(true); + SaRecord.setSaRecordHelper(mMockSaRecordHelper); + + setUpPayloadLists(); + setUpChildSaRecords(); + + mChildSessionStateMachine.start(); + } + + private void setUpPayloadLists() throws IkeException { + mAuthReqSaNegoPayloads.add( + TestUtils.hexStringToIkePayload( + IkePayload.PAYLOAD_TYPE_SA, IKE_AUTH_REQ_SA_PAYLOAD)); + mAuthRespSaNegoPayloads.add( + TestUtils.hexStringToIkePayload( + IkePayload.PAYLOAD_TYPE_SA, IKE_AUTH_RESP_SA_PAYLOAD)); + // TODO: Build and add Traffic Selector Payloads to two payload lists. + } + + private void setUpChildSaRecords() { + mSpyCurrentChildSaRecord = + spy(makeDummyChildSaRecord(CURRENT_CHILD_SA_SPI_IN, CURRENT_CHILD_SA_SPI_OUT)); + } + + private ChildSaRecord makeDummyChildSaRecord(String inboundSpiHex, String outboundSpiHex) { + byte[] spiInBytes = TestUtils.hexStringToByteArray(CURRENT_CHILD_SA_SPI_IN); + int spiIn = ByteBuffer.wrap(spiInBytes).getInt(); + + byte[] spiOutBytes = TestUtils.hexStringToByteArray(CURRENT_CHILD_SA_SPI_OUT); + int spiOut = ByteBuffer.wrap(spiOutBytes).getInt(); + + return new ChildSaRecord(spiIn, spiOut, null, null); + } + + @After + public void tearDown() { + mChildSessionStateMachine.quit(); + mChildSessionStateMachine.setDbg(false); + + SaRecord.setSaRecordHelper(new SaRecordHelper()); + } + + @Test + public void testCreateFirstChild() throws Exception { + when(mMockSaRecordHelper.makeChildSaRecord(any(), any())) + .thenReturn(mSpyCurrentChildSaRecord); + mChildSessionStateMachine.handleFirstChildExchange( + mAuthReqSaNegoPayloads, mAuthRespSaNegoPayloads, mMockChildSessionCallback); + + mLooper.dispatchAll(); + verify(mMockChildSessionCallback) + .onCreateChildSa(mSpyCurrentChildSaRecord.outboundSpi, mChildSessionStateMachine); + assertTrue( + mChildSessionStateMachine.getCurrentState() + instanceof ChildSessionStateMachine.Idle); + assertEquals(mSpyCurrentChildSaRecord, mChildSessionStateMachine.mCurrentChildSaRecord); + } +} diff --git a/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionStateMachineTest.java b/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionStateMachineTest.java index b70e5865..02aaa4c3 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionStateMachineTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionStateMachineTest.java @@ -29,6 +29,8 @@ import static org.mockito.Mockito.when; import android.os.test.TestLooper; import android.util.Pair; +import com.android.ike.ikev2.ChildSessionStateMachineFactory.ChildSessionFactoryHelper; +import com.android.ike.ikev2.ChildSessionStateMachineFactory.IChildSessionFactoryHelper; import com.android.ike.ikev2.IkeSessionStateMachine.ReceivedIkePacket; import com.android.ike.ikev2.SaRecord.ISaRecordHelper; import com.android.ike.ikev2.SaRecord.IkeSaRecord; @@ -53,6 +55,11 @@ public final class IkeSessionStateMachineTest { private IIkeMessageHelper mMockIkeMessageHelper; private ISaRecordHelper mMockSaRecordHelper; private IkeSessionOptions mMockIkeSessionOptions; + + private ChildSessionStateMachine mMockChildSessionStateMachine; + private ChildSessionOptions mMockChildSessionOptions; + private IChildSessionFactoryHelper mMockChildSessionFactoryHelper; + private IkeSaRecord mSpyCurrentIkeSaRecord; private IkeSaRecord mSpyLocalInitIkeSaRecord; private IkeSaRecord mSpyRemoteInitIkeSaRecord; @@ -110,12 +117,18 @@ public final class IkeSessionStateMachineTest { mMockSaRecordHelper = mock(SaRecord.ISaRecordHelper.class); mMockIkeSessionOptions = mock(IkeSessionOptions.class); + mMockChildSessionStateMachine = mock(ChildSessionStateMachine.class); + mMockChildSessionOptions = mock(ChildSessionOptions.class); + mMockChildSessionFactoryHelper = mock(IChildSessionFactoryHelper.class); + mSpyCurrentIkeSaRecord = spy(new IkeSaRecord(11, 12, true, null, null)); mSpyLocalInitIkeSaRecord = spy(new IkeSaRecord(21, 22, true, null, null)); mSpyRemoteInitIkeSaRecord = spy(new IkeSaRecord(31, 32, false, null, null)); when(mMockIkeMessageHelper.encode(any())).thenReturn(new byte[0]); when(mMockIkeMessageHelper.encode(any(), any(), any())).thenReturn(new byte[0]); + when(mMockChildSessionFactoryHelper.makeChildSessionStateMachine(any(), any(), any())) + .thenReturn(mMockChildSessionStateMachine); } @Before @@ -124,11 +137,16 @@ public final class IkeSessionStateMachineTest { mLooper = new TestLooper(); mIkeSessionStateMachine = new IkeSessionStateMachine( - "IkeSessionStateMachine", mLooper.getLooper(), mMockIkeSessionOptions); + "IkeSessionStateMachine", + mLooper.getLooper(), + mMockIkeSessionOptions, + mMockChildSessionOptions); mIkeSessionStateMachine.setDbg(true); mIkeSessionStateMachine.start(); IkeMessage.setIkeMessageHelper(mMockIkeMessageHelper); SaRecord.setSaRecordHelper(mMockSaRecordHelper); + ChildSessionStateMachineFactory.setChildSessionFactoryHelper( + mMockChildSessionFactoryHelper); } @After @@ -137,6 +155,8 @@ public final class IkeSessionStateMachineTest { mIkeSessionStateMachine.setDbg(false); IkeMessage.setIkeMessageHelper(new IkeMessageHelper()); SaRecord.setSaRecordHelper(new SaRecordHelper()); + ChildSessionStateMachineFactory.setChildSessionFactoryHelper( + new ChildSessionFactoryHelper()); } @Test @@ -186,6 +206,7 @@ public final class IkeSessionStateMachineTest { mLooper.dispatchAll(); verify(mMockIkeMessageHelper).decode(any(), any(), any(), any()); verify(mMockIkeMessageHelper, times(2)).getMessageType(any()); + verify(mMockChildSessionStateMachine).handleFirstChildExchange(any(), any(), any()); assertTrue( mIkeSessionStateMachine.getCurrentState() instanceof IkeSessionStateMachine.Idle); } diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/TestUtils.java b/tests/iketests/src/java/com/android/ike/ikev2/message/TestUtils.java index e77e799d..ac3d5018 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/TestUtils.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/TestUtils.java @@ -16,15 +16,15 @@ package com.android.ike.ikev2.message; +import android.util.Pair; + +import com.android.ike.ikev2.exceptions.IkeException; + +import java.nio.ByteBuffer; + /** TestUtils provides utility methods for parsing Hex String */ public final class TestUtils { - /** - * Converts the unsigned Hex String to a byte array. - * - * @param hexString hex representation of an unsigned value. - * @return the converted byte array. - * @throws IllegalArgumentException when length of Hex String is an odd number. - */ + public static byte[] hexStringToByteArray(String hexString) throws IllegalArgumentException { int len = hexString.length(); if (len % 2 != 0) { @@ -39,4 +39,13 @@ public final class TestUtils { } return data; } + + public static IkePayload hexStringToIkePayload( + @IkePayload.PayloadType int payloadType, String payloadHexString) throws IkeException { + byte[] payloadBytes = hexStringToByteArray(payloadHexString); + // Returned Pair consists of the IkePayload and the following IkePayload's type. + Pair pair = + IkePayloadFactory.getIkePayload(payloadType, ByteBuffer.wrap(payloadBytes)); + return pair.first; + } } -- cgit v1.2.3