From 02d1755091ad12178640e34699cb3e57e1053f26 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Fri, 25 Oct 2019 15:26:23 -0700 Subject: Add end-to-end testing for EAP-AKA'. Bug: 142667016 Test: added EapAkaPrimeTest. Test: atest FrameworksIkeTests Change-Id: I068f091497de88b031c541b3fb677b997451a111 --- .../java/com/android/ike/eap/EapAkaPrimeTest.java | 381 +++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 tests/iketests/src/java/com/android/ike/eap/EapAkaPrimeTest.java diff --git a/tests/iketests/src/java/com/android/ike/eap/EapAkaPrimeTest.java b/tests/iketests/src/java/com/android/ike/eap/EapAkaPrimeTest.java new file mode 100644 index 00000000..d8f43295 --- /dev/null +++ b/tests/iketests/src/java/com/android/ike/eap/EapAkaPrimeTest.java @@ -0,0 +1,381 @@ +/* + * 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.eap; + +import static android.telephony.TelephonyManager.APPTYPE_USIM; + +import static com.android.ike.TestUtils.hexStringToByteArray; +import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_REQUEST_SIM_START_PACKET; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.telephony.TelephonyManager; + +import com.android.ike.eap.statemachine.EapStateMachine; + +import org.junit.Before; +import org.junit.Test; + +public class EapAkaPrimeTest extends EapMethodEndToEndTest { + private static final long AUTHENTICATOR_TIMEOUT_MILLIS = 250L; + + private static final int SUB_ID = 1; + private static final String UNFORMATTED_IDENTITY = "123456789ABCDEF"; // IMSI + + // EAP_IDENTITY = hex("test@android.net") + private static final byte[] EAP_IDENTITY = + hexStringToByteArray("7465737440616E64726F69642E6E6574"); + private static final boolean ALLOW_MISMATCHED_NETWORK_NAMES = false; + private static final String PEER_NETWORK_NAME_1 = "foo:bar"; + private static final String PEER_NETWORK_NAME_2 = "bar"; + + // hex("foo:bar:buzz") + private static final String SERVER_NETWORK_NAME = "666F6F3A6261723A62757A7A"; + + // TODO(b/142667016): replace with externally generated test values + + // IK: 7320EE404E055EF2B5AB0F86E96C48BE + // CK: E9D1707652E13BF3E05975F601678E5C + // Server Network Name: 666F6F3A6261723A62757A7A + // SQN ^ AK: 35A9143ED9E1 + // IK': 79DC30692F3D2303D148549E5D50D0AA + // CK': BBD0A7AD3F14757BA604C4CBE70F9090 + // K_encr: 4c22c289bcf40367cf2bdb6a6e3fe56b + // K_aut: c64abd508ab628f842e9fb40a14fea769d2ccc67a8412794fe3b4c2556431e78 + // K_re: 5454ccf7ecc227f25c6cd1023e09394fa5cedc14a2f155e9d96a70dc404b4dca + private static final String RAND_1 = "D6A296F030A305601B311D38A004505C"; + private static final String RAND_2 = "000102030405060708090A0B0C0D0E0F"; + private static final String AUTN = "35A9143ED9E100011795E785DAFAAD9B"; + private static final String RES = "E5167A255FDCDE9248AF6B50ADA0D944"; + private static final String AUTS = "0102030405060708090A0B0C0D0E"; + private static final byte[] MSK = + hexStringToByteArray( + "695788d8f33af56b5b2fea065a0e8656" + + "7dc48120d6070d96056f9668614ec3e7" + + "feb4933a3aaab3587980a624998c8b5e" + + "a69d7295b824ef4a2201720be89d04df"); + private static final byte[] EMSK = + hexStringToByteArray( + "2db1f574d6e92cec294779defef5a7f0" + + "49319cc75367102815d0244087f23660" + + "0986b47a862c1aeeca418c84a2f9581b" + + "0738fdefd229a5f7a4ca76709379bf00"); + + // IK: 7320EE404E055EF2B5AB0F86E96C48BE + // CK: E9D1707652E13BF3E05975F601678E5C + // Server Network Name: 666F6F3A6261723A62757A7A + // SQN ^ AK: 35A9143ED9E1 + // IK': 6C45FB0B12FF8172223B6D0E599EAE20 + // CK': A01C894696BEB759ABE0340F71A20D7B + // K_encr: c039213c78fcf78a34bef30219a77822 + // K_aut: 95b014e569144eba71a387f91fb6b72e06781df12d61bfe88e5149477cd232aa + // K_re: 1000c2e2f01766a4d2581ac454e41fce1ee17bcccbc32dfad78815075d884c5e + private static final byte[] MSK_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "ad75a86586773134dcd9e78e3f75b282" + + "7a42435cb1be7235be58cddc60a0ba19" + + "dd5c30accfdb0db5ef065f46c3c25d7b" + + "9f8703d9493a2dc6fb6563dbdc854658"); + private static final byte[] EMSK_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "31a3f2bb0e3e831d991dc8666438297f" + + "4a5bc157fc1e31537e5a4927206d7b4b" + + "db830761eea3441d9b90da48aebb9734" + + "d3cbdec96072230a64043f54932a8841"); + + // Base 64 of: [Length][RAND_1][Length][AUTN] + private static final String BASE64_CHALLENGE_1 = + "ENailvAwowVgGzEdOKAEUFwQNakUPtnhAAEXleeF2vqtmw=="; + + // Base 64 of: ['DB'][Length][RES][Length][IK][Length][CK] + private static final String BASE_64_RESPONSE_SUCCESS = + "2xDlFnolX9zekkiva1CtoNlEEHMg7kBOBV7ytasPhulsSL4Q6dFwdlLhO/PgWXX2AWeOXA=="; + + // Base 64 of: [Length][RAND_2][Length][AUTN] + private static final String BASE64_CHALLENGE_2 = + "EAABAgMEBQYHCAkKCwwNDg8QNakUPtnhAAEXleeF2vqtmw=="; + + // Base 64 of: ['DC'][Length][AUTS] + private static final String BASE_64_RESPONSE_SYNC_FAIL = "3A4BAgMEBQYHCAkKCwwNDg=="; + + private static final String REQUEST_MAC = "9089f89b2f99bb85f2f2b529779f98db"; + private static final String RESPONSE_MAC = "48d7d6a80e1e2ff26a1e4148e0a2303e"; + private static final String REQUEST_MAC_WITHOUT_IDENTITY_REQ = + "59f680ede020a3d0156eef56affb6997"; + private static final String RESPONSE_MAC_WITHOUT_IDENTITY_REQ = + "e15322ff4abe51479c0fa92d00e343d7"; + + private static final byte[] EAP_AKA_PRIME_IDENTITY_REQUEST = + hexStringToByteArray( + "01CD000C" // EAP-Request | ID | length in bytes + + "32050000" // EAP-AKA' | Identity | 2B padding + + "0D010000"); // AT_ANY_ID_REQ attribute + private static final byte[] EAP_AKA_PRIME_IDENTITY_RESPONSE = + hexStringToByteArray( + "02CD001C" // EAP-Response | ID | length in bytes + + "32050000" // EAP-AKA' | Identity | 2B padding + + "0E05001036313233343536373839414243444546"); // AT_IDENTITY attribute + + private static final byte[] EAP_AKA_PRIME_CHALLENGE_REQUEST = + hexStringToByteArray( + "01CE0044" // EAP-Request | ID | length in bytes + + "32010000" // EAP-AKA' | Challenge | 2B padding + + "01050000" + RAND_1 // AT_RAND attribute + + "02050000" + AUTN // AT_AUTN attribute + + "1704000C" + SERVER_NETWORK_NAME // AT_KDF_INPUT attribute + + "18010001" // AT_KDF attribute + + "0B050000" + REQUEST_MAC); // AT_MAC attribute + private static final byte[] EAP_AKA_PRIME_CHALLENGE_RESPONSE = + hexStringToByteArray( + "02CE0030" // EAP-Response | ID | length in bytes + + "32010000" // EAP-AKA' | Challenge | 2B padding + + "03050080" + RES // AT_RES attribute + + "0B050000" + RESPONSE_MAC); // AT_MAC attribute + + private static final byte[] EAP_AKA_PRIME_CHALLENGE_REQUEST_WITHOUT_IDENTITY_REQ = + hexStringToByteArray( + "01CE0044" // EAP-Request | ID | length in bytes + + "32010000" // EAP-AKA' | Challenge | 2B padding + + "01050000" + RAND_1 // AT_RAND attribute + + "02050000" + AUTN // AT_AUTN attribute + + "1704000C" + SERVER_NETWORK_NAME // AT_KDF_INPUT attribute + + "18010001" // AT_KDF attribute + + "0B050000" + REQUEST_MAC_WITHOUT_IDENTITY_REQ); // AT_MAC attribute + private static final byte[] EAP_AKA_PRIME_CHALLENGE_RESPONSE_WITHOUT_IDENTITY_REQUEST = + hexStringToByteArray( + "02CE0030" // EAP-Response | ID | length in bytes + + "32010000" // EAP-AKA' | Challenge | 2B padding + + "03050080" + RES // AT_RES attribute + + "0B050000" + RESPONSE_MAC_WITHOUT_IDENTITY_REQ); // AT_MAC attribute + + private static final byte[] EAP_AKA_PRIME_CHALLENGE_REQUEST_SYNC_FAIL = + hexStringToByteArray( + "01CE0044" // EAP-Request | ID | length in bytes + + "32010000" // EAP-AKA' | Challenge | 2B padding + + "01050000" + RAND_2 // AT_RAND attribute + + "02050000" + AUTN // AT_AUTN attribute + + "1704000C" + SERVER_NETWORK_NAME // AT_KDF_INPUT attribute + + "18010001" // AT_KDF attribute + + "0B050000" + REQUEST_MAC); // AT_MAC attribute + private static final byte[] EAP_AKA_PRIME_SYNC_FAIL_RESPONSE = + hexStringToByteArray( + "02CE0018" // EAP-Response | ID | length in bytes + + "32040000" // EAP-AKA' | Synchronization-Failure | 2B padding + + "0404" + AUTS); // AT_AUTS attribute + + private static final byte[] EAP_AKA_PRIME_AUTHENTICATION_REJECT = + hexStringToByteArray( + "02CE0008" // EAP-Response | ID | length in bytes + + "32020000"); // EAP-AKA' | Authentication-Reject | 2B padding + + private static final byte[] EAP_RESPONSE_NAK_PACKET = + hexStringToByteArray("021000060332"); // NAK with EAP-AKA' listed + + private TelephonyManager mMockTelephonyManager; + + @Before + @Override + public void setUp() { + super.setUp(); + + setUp(ALLOW_MISMATCHED_NETWORK_NAMES, PEER_NETWORK_NAME_1); + } + + private void setUp(boolean allowMismatchedNetworkNames, String peerNetworkName) { + mMockTelephonyManager = mock(TelephonyManager.class); + + mEapSessionConfig = + new EapSessionConfig.Builder() + .setEapIdentity(EAP_IDENTITY) + .setEapAkaPrimeConfig( + SUB_ID, APPTYPE_USIM, peerNetworkName, allowMismatchedNetworkNames) + .build(); + mEapAuthenticator = + new EapAuthenticator( + mTestLooper.getLooper(), + mMockCallback, + new EapStateMachine(mMockContext, mEapSessionConfig, mMockSecureRandom), + (runnable) -> runnable.run(), + AUTHENTICATOR_TIMEOUT_MILLIS); + + when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE)) + .thenReturn(mMockTelephonyManager); + when(mMockTelephonyManager.createForSubscriptionId(SUB_ID)) + .thenReturn(mMockTelephonyManager); + } + + @Test + public void testEapAkaPrimeEndToEnd() { + verifyEapPrimeAkaIdentity(); + verifyEapAkaPrimeChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_PRIME_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); + } + + @Test + public void testEapAkaPrimeEndToEndWithoutIdentityRequest() { + verifyEapAkaPrimeChallengeWithoutIdentityReq(); + verifyEapSuccess(MSK_WITHOUT_IDENTITY_REQ, EMSK_WITHOUT_IDENTITY_REQ); + } + + @Test + public void testEapAkaPrimeWithEapNotifications() { + verifyEapNotification(1); + verifyEapPrimeAkaIdentity(); + + verifyEapNotification(2); + verifyEapAkaPrimeChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_PRIME_CHALLENGE_RESPONSE); + + verifyEapNotification(3); + verifyEapSuccess(MSK, EMSK); + } + + @Test + public void testEapAkaPrimeUnsupportedType() { + verifyUnsupportedType(EAP_REQUEST_SIM_START_PACKET, EAP_RESPONSE_NAK_PACKET); + + verifyEapPrimeAkaIdentity(); + verifyEapAkaPrimeChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_PRIME_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); + } + + @Test + public void testEapAkaPrimeSynchronizationFailure() { + verifyEapPrimeAkaIdentity(); + verifyEapAkaPrimeSynchronizationFailure(); + verifyEapAkaPrimeChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_PRIME_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); + } + + @Test + public void testEapAkaPrimeAuthenticationReject() { + verifyEapPrimeAkaIdentity(); + + // return null from TelephonyManager to simluate rejection of AUTN + verifyEapAkaPrimeChallenge(null, EAP_AKA_PRIME_AUTHENTICATION_REJECT); + verifyEapFailure(); + } + + @Test + public void testEapAkaPrimeMismatchedNetworkNamesNotAllowed() { + // use mismatched peer network name + setUp(false, PEER_NETWORK_NAME_2); + verifyEapPrimeAkaIdentity(); + verifyEapAkaPrimeChallengeMismatchedNetworkNames(); + verifyEapFailure(); + } + + @Test + public void testEapAkaPrimeMismatchedNetworkNamesAllowed() { + setUp(true, PEER_NETWORK_NAME_2); + verifyEapPrimeAkaIdentity(); + verifyEapAkaPrimeChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_PRIME_CHALLENGE_RESPONSE); + verifyEapSuccess(MSK, EMSK); + } + + private void verifyEapPrimeAkaIdentity() { + // EAP-AKA'/Identity request + when(mMockTelephonyManager.getSubscriberId()).thenReturn(UNFORMATTED_IDENTITY); + + mEapAuthenticator.processEapMessage(EAP_AKA_PRIME_IDENTITY_REQUEST); + mTestLooper.dispatchAll(); + + // verify EAP-AKA'/Identity response + verify(mMockContext).getSystemService(eq(Context.TELEPHONY_SERVICE)); + verify(mMockTelephonyManager).createForSubscriptionId(SUB_ID); + verify(mMockTelephonyManager).getSubscriberId(); + verify(mMockCallback).onResponse(eq(EAP_AKA_PRIME_IDENTITY_RESPONSE)); + verifyNoMoreInteractions( + mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); + } + + private void verifyEapAkaPrimeChallenge( + String challengeBase64, + String responseBase64, + byte[] incomingEapPacket, + byte[] outgoingEapPacket) { + // EAP-AKA'/Challenge request + when(mMockTelephonyManager.getIccAuthentication( + TelephonyManager.APPTYPE_USIM, + TelephonyManager.AUTHTYPE_EAP_AKA, + challengeBase64)) + .thenReturn(responseBase64); + + mEapAuthenticator.processEapMessage(incomingEapPacket); + mTestLooper.dispatchAll(); + + // verify EAP-AKA'/Challenge response + verify(mMockTelephonyManager) + .getIccAuthentication( + TelephonyManager.APPTYPE_USIM, + TelephonyManager.AUTHTYPE_EAP_AKA, + challengeBase64); + verify(mMockCallback).onResponse(eq(outgoingEapPacket)); + } + + private void verifyEapAkaPrimeChallenge(String responseBase64, byte[] outgoingPacket) { + verifyEapAkaPrimeChallenge( + BASE64_CHALLENGE_1, + responseBase64, + EAP_AKA_PRIME_CHALLENGE_REQUEST, + outgoingPacket); + verifyNoMoreInteractions( + mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); + } + + private void verifyEapAkaPrimeChallengeWithoutIdentityReq() { + verifyEapAkaPrimeChallenge( + BASE64_CHALLENGE_1, + BASE_64_RESPONSE_SUCCESS, + EAP_AKA_PRIME_CHALLENGE_REQUEST_WITHOUT_IDENTITY_REQ, + EAP_AKA_PRIME_CHALLENGE_RESPONSE_WITHOUT_IDENTITY_REQUEST); + + // also need to verify interactions with Context and TelephonyManager + verify(mMockContext).getSystemService(eq(Context.TELEPHONY_SERVICE)); + verify(mMockTelephonyManager).createForSubscriptionId(SUB_ID); + verifyNoMoreInteractions( + mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); + } + + private void verifyEapAkaPrimeSynchronizationFailure() { + verifyEapAkaPrimeChallenge( + BASE64_CHALLENGE_2, + BASE_64_RESPONSE_SYNC_FAIL, + EAP_AKA_PRIME_CHALLENGE_REQUEST_SYNC_FAIL, + EAP_AKA_PRIME_SYNC_FAIL_RESPONSE); + verifyNoMoreInteractions( + mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback); + } + + private void verifyEapAkaPrimeChallengeMismatchedNetworkNames() { + // EAP-AKA'/Challenge request + mEapAuthenticator.processEapMessage(EAP_AKA_PRIME_CHALLENGE_REQUEST); + mTestLooper.dispatchAll(); + verify(mMockCallback).onResponse(eq(EAP_AKA_PRIME_AUTHENTICATION_REJECT)); + } + + @Override + protected void verifyEapSuccess(byte[] msk, byte[] emsk) { + super.verifyEapSuccess(msk, emsk); + + verifyNoMoreInteractions(mMockTelephonyManager); + } +} -- cgit v1.2.3 From bdf11e741848a568b7459688212f7e71efae8ba1 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Tue, 29 Oct 2019 12:38:18 -0700 Subject: Remove unnecessary logging for Sha256ByteSigner. Bug: 142668075 Test: atest FrameworksIkeTests Change-Id: Ie3f614491a7827cb30551695ae4c6601d9fa111d --- src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java b/src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java index db511ebc..f5d4149f 100644 --- a/src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java +++ b/src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java @@ -16,8 +16,6 @@ package com.android.ike.eap.crypto; -import static com.android.ike.eap.EapAuthenticator.LOG; - import com.android.ike.crypto.KeyGenerationUtils; import com.android.ike.crypto.KeyGenerationUtils.ByteSigner; @@ -52,7 +50,6 @@ public class HmacSha256ByteSigner implements KeyGenerationUtils.ByteSigner { mac.init(new SecretKeySpec(keyBytes, MAC_ALGORITHM_STRING)); return mac.doFinal(dataToSign); } catch (NoSuchAlgorithmException | InvalidKeyException ex) { - LOG.wtf(TAG, "Error computing HMAC-SHA-256", ex); throw new IllegalArgumentException(ex); } } -- cgit v1.2.3 From e27a40124c6885b385cef49f7ae3132c323e00c1 Mon Sep 17 00:00:00 2001 From: evitayan Date: Thu, 7 Nov 2019 10:45:28 -0800 Subject: Make methods public for separating API and Impl This commit makes several methods from package private to public so that later we can separate API and Impl to different packages Bug: 143983419 Test: atest FrameworksIkeTests(all tests passed) Change-Id: Ie08b5ab6bdf8b27a523a4b6f28a83bbf2b02bbe0 --- src/java/com/android/ike/eap/EapSessionConfig.java | 2 +- .../com/android/ike/ikev2/ChildSaProposal.java | 8 +-- .../ike/ikev2/ChildSessionConfiguration.java | 12 ++-- .../com/android/ike/ikev2/ChildSessionOptions.java | 12 ++-- src/java/com/android/ike/ikev2/IkeManager.java | 6 +- src/java/com/android/ike/ikev2/IkeSaProposal.java | 4 +- .../com/android/ike/ikev2/IkeSessionOptions.java | 78 ++++++++++------------ .../android/ike/ikev2/IkeSessionStateMachine.java | 28 +++++--- src/java/com/android/ike/ikev2/SaProposal.java | 9 +-- .../ike/ikev2/TunnelModeChildSessionOptions.java | 3 +- .../ike/ikev2/IkeSessionStateMachineTest.java | 2 +- 11 files changed, 81 insertions(+), 83 deletions(-) diff --git a/src/java/com/android/ike/eap/EapSessionConfig.java b/src/java/com/android/ike/eap/EapSessionConfig.java index 285dc799..e3d77432 100644 --- a/src/java/com/android/ike/eap/EapSessionConfig.java +++ b/src/java/com/android/ike/eap/EapSessionConfig.java @@ -46,7 +46,7 @@ public final class EapSessionConfig { public final byte[] eapIdentity; @VisibleForTesting - EapSessionConfig(Map eapConfigs, byte[] eapIdentity) { + public EapSessionConfig(Map eapConfigs, byte[] eapIdentity) { this.eapConfigs = Collections.unmodifiableMap(eapConfigs); this.eapIdentity = eapIdentity; } diff --git a/src/java/com/android/ike/ikev2/ChildSaProposal.java b/src/java/com/android/ike/ikev2/ChildSaProposal.java index 92c717e5..264890f4 100644 --- a/src/java/com/android/ike/ikev2/ChildSaProposal.java +++ b/src/java/com/android/ike/ikev2/ChildSaProposal.java @@ -59,17 +59,17 @@ public final class ChildSaProposal extends SaProposal { mEsns = esns; } - /** Package private method to get ESN policies. */ - EsnTransform[] getEsnTransforms() { + /** Gets all ESN policies. */ + public EsnTransform[] getEsnTransforms() { return mEsns; } /** - * Package private method to get a copy of proposal without all proposed DH groups. + * Gets a copy of proposal without all proposed DH groups. * *

This is used to avoid negotiating DH Group for negotiating first Child SA. */ - ChildSaProposal getCopyWithoutDhTransform() { + public ChildSaProposal getCopyWithoutDhTransform() { return new ChildSaProposal( getEncryptionTransforms(), getIntegrityTransforms(), diff --git a/src/java/com/android/ike/ikev2/ChildSessionConfiguration.java b/src/java/com/android/ike/ikev2/ChildSessionConfiguration.java index 555feb05..b2c1c76d 100644 --- a/src/java/com/android/ike/ikev2/ChildSessionConfiguration.java +++ b/src/java/com/android/ike/ikev2/ChildSessionConfiguration.java @@ -41,11 +41,12 @@ public final class ChildSessionConfiguration { private final List mInternalAddressList; /** - * Package private constructor for building an ChildSessionConfiguration + * Construct an instance of {@link ChildSessionConfiguration}. * - *

It is only supported to build a ChildSessionConfiguration with a Configure(Reply) Payload. + *

It is only supported to build a {@link ChildSessionConfiguration} with a Configure(Reply) + * Payload. */ - ChildSessionConfiguration( + public ChildSessionConfiguration( List inTs, List outTs, IkeConfigPayload configPayload) { @@ -91,8 +92,9 @@ public final class ChildSessionConfiguration { } } - /** Package private constructor for building an ChildSessionConfiguration */ - ChildSessionConfiguration(List inTs, List outTs) { + /** Construct an instance of {@link ChildSessionConfiguration}. */ + public ChildSessionConfiguration( + List inTs, List outTs) { mInboundTs = Collections.unmodifiableList(inTs); mOutboundTs = Collections.unmodifiableList(outTs); mInternalAddressList = new LinkedList<>(); diff --git a/src/java/com/android/ike/ikev2/ChildSessionOptions.java b/src/java/com/android/ike/ikev2/ChildSessionOptions.java index 0519416d..fe7a12e0 100644 --- a/src/java/com/android/ike/ikev2/ChildSessionOptions.java +++ b/src/java/com/android/ike/ikev2/ChildSessionOptions.java @@ -53,23 +53,19 @@ public abstract class ChildSessionOptions { mIsTransport = isTransport; } - /** Package private */ - IkeTrafficSelector[] getLocalTrafficSelectors() { + public IkeTrafficSelector[] getLocalTrafficSelectors() { return mLocalTrafficSelectors; } - /** Package private */ - IkeTrafficSelector[] getRemoteTrafficSelectors() { + public IkeTrafficSelector[] getRemoteTrafficSelectors() { return mRemoteTrafficSelectors; } - /** Package private */ - ChildSaProposal[] getSaProposals() { + public ChildSaProposal[] getSaProposals() { return mSaProposals; } - /** Package private */ - boolean isTransportMode() { + public boolean isTransportMode() { return mIsTransport; } diff --git a/src/java/com/android/ike/ikev2/IkeManager.java b/src/java/com/android/ike/ikev2/IkeManager.java index 38ab15ba..08b93a0a 100644 --- a/src/java/com/android/ike/ikev2/IkeManager.java +++ b/src/java/com/android/ike/ikev2/IkeManager.java @@ -80,13 +80,15 @@ public final class IkeManager { return sIkeLog; } + /** Injects IKE logger for testing. */ @VisibleForTesting - static void setIkeLog(Log log) { + public static void setIkeLog(Log log) { sIkeLog = log; } + /** Resets IKE logger. */ @VisibleForTesting - static void resetIkeLog() { + public static void resetIkeLog() { sIkeLog = new Log(IKE_TAG, LOG_SENSITIVE); } } diff --git a/src/java/com/android/ike/ikev2/IkeSaProposal.java b/src/java/com/android/ike/ikev2/IkeSaProposal.java index 788c7f9e..bb13b607 100644 --- a/src/java/com/android/ike/ikev2/IkeSaProposal.java +++ b/src/java/com/android/ike/ikev2/IkeSaProposal.java @@ -62,8 +62,8 @@ public final class IkeSaProposal extends SaProposal { mPseudorandomFunctions = prfs; } - /** Package private method to get all PRFs. */ - PrfTransform[] getPrfTransforms() { + /** Gets all PRFs. */ + public PrfTransform[] getPrfTransforms() { return mPseudorandomFunctions; } diff --git a/src/java/com/android/ike/ikev2/IkeSessionOptions.java b/src/java/com/android/ike/ikev2/IkeSessionOptions.java index d7222256..b66630d1 100644 --- a/src/java/com/android/ike/ikev2/IkeSessionOptions.java +++ b/src/java/com/android/ike/ikev2/IkeSessionOptions.java @@ -43,10 +43,10 @@ public final class IkeSessionOptions { @IntDef({IKE_AUTH_METHOD_PSK, IKE_AUTH_METHOD_PUB_KEY_SIGNATURE, IKE_AUTH_METHOD_EAP}) public @interface IkeAuthMethod {} - // Package private constants to describe user configured authentication methods. - static final int IKE_AUTH_METHOD_PSK = 1; - static final int IKE_AUTH_METHOD_PUB_KEY_SIGNATURE = 2; - static final int IKE_AUTH_METHOD_EAP = 3; + // Constants to describe user configured authentication methods. + public static final int IKE_AUTH_METHOD_PSK = 1; + public static final int IKE_AUTH_METHOD_PUB_KEY_SIGNATURE = 2; + public static final int IKE_AUTH_METHOD_EAP = 3; private final InetAddress mServerAddress; private final UdpEncapsulationSocket mUdpEncapSocket; @@ -82,44 +82,40 @@ public final class IkeSessionOptions { mIsIkeFragmentationSupported = isIkeFragmentationSupported; } - /** Package private */ - InetAddress getServerAddress() { + public InetAddress getServerAddress() { return mServerAddress; } - /** Package private */ - UdpEncapsulationSocket getUdpEncapsulationSocket() { + + public UdpEncapsulationSocket getUdpEncapsulationSocket() { return mUdpEncapSocket; } - /** Package private */ - IkeSaProposal[] getSaProposals() { + + public IkeSaProposal[] getSaProposals() { return mSaProposals; } - /** Package private */ - IkeIdentification getLocalIdentification() { + + public IkeIdentification getLocalIdentification() { return mLocalIdentification; } - /** Package private */ - IkeIdentification getRemoteIdentification() { + + public IkeIdentification getRemoteIdentification() { return mRemoteIdentification; } - /** Package private */ - IkeAuthConfig getLocalAuthConfig() { + + public IkeAuthConfig getLocalAuthConfig() { return mLocalAuthConfig; } - /** Package private */ - IkeAuthConfig getRemoteAuthConfig() { + + public IkeAuthConfig getRemoteAuthConfig() { return mRemoteAuthConfig; } - /** Package private */ - boolean isIkeFragmentationSupported() { + + public boolean isIkeFragmentationSupported() { return mIsIkeFragmentationSupported; } - /** - * Package private class that contains common information of an IKEv2 authentication - * configuration. - */ - abstract static class IkeAuthConfig { - @IkeAuthMethod final int mAuthMethod; + /** This class contains common information of an IKEv2 authentication configuration. */ + public abstract static class IkeAuthConfig { + @IkeAuthMethod public final int mAuthMethod; protected IkeAuthConfig(@IkeAuthMethod int authMethod) { mAuthMethod = authMethod; @@ -127,11 +123,11 @@ public final class IkeSessionOptions { } /** - * Package private class that contains configuration for IKEv2 pre-shared-key-based - * authentication of local or remote side. + * This class represents the configuration to support IKEv2 pre-shared-key-based authentication + * of local or remote side. */ - static class IkeAuthPskConfig extends IkeAuthConfig { - final byte[] mPsk; + public static class IkeAuthPskConfig extends IkeAuthConfig { + public final byte[] mPsk; private IkeAuthPskConfig(byte[] psk) { super(IKE_AUTH_METHOD_PSK); @@ -140,11 +136,11 @@ public final class IkeSessionOptions { } /** - * Package private class that contains configuration for IKEv2 public-key-signature-based + * This class represents the configuration to support IKEv2 public-key-signature-based * authentication of the remote side. */ - static class IkeAuthDigitalSignRemoteConfig extends IkeAuthConfig { - final TrustAnchor mTrustAnchor; + public static class IkeAuthDigitalSignRemoteConfig extends IkeAuthConfig { + public final TrustAnchor mTrustAnchor; private IkeAuthDigitalSignRemoteConfig(TrustAnchor trustAnchor) { super(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE); @@ -153,13 +149,13 @@ public final class IkeSessionOptions { } /** - * Package private class that contains configuration to do IKEv2 public-key-signature-based + * This class represents the configuration to support IKEv2 public-key-signature-based * authentication of the local side. */ - static class IkeAuthDigitalSignLocalConfig extends IkeAuthConfig { - final X509Certificate mEndCert; - final List mIntermediateCerts; - final PrivateKey mPrivateKey; + public static class IkeAuthDigitalSignLocalConfig extends IkeAuthConfig { + public final X509Certificate mEndCert; + public final List mIntermediateCerts; + public final PrivateKey mPrivateKey; private IkeAuthDigitalSignLocalConfig( X509Certificate clientEndCert, @@ -173,7 +169,7 @@ public final class IkeSessionOptions { } /** - * Package private class that contains configuration to do EAP authentication of the local side. + * This class represents the configuration to support EAP authentication of the local side. * *

EAP MUST be used with IKEv2 public-key-based authentication of the responder to the * initiator. Currently IKE library does not support the IKEv2 protocol extension(RFC 5998) @@ -184,8 +180,8 @@ public final class IkeSessionOptions { * @see RFC 5998, An Extension for EAP-Only * Authentication in IKEv2 */ - static class IkeAuthEapConfig extends IkeAuthConfig { - final EapSessionConfig mEapConfig; + public static class IkeAuthEapConfig extends IkeAuthConfig { + public final EapSessionConfig mEapConfig; private IkeAuthEapConfig(EapSessionConfig eapConfig) { super(IKE_AUTH_METHOD_EAP); diff --git a/src/java/com/android/ike/ikev2/IkeSessionStateMachine.java b/src/java/com/android/ike/ikev2/IkeSessionStateMachine.java index 3e5d9796..e9b0dc83 100644 --- a/src/java/com/android/ike/ikev2/IkeSessionStateMachine.java +++ b/src/java/com/android/ike/ikev2/IkeSessionStateMachine.java @@ -375,9 +375,9 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { @VisibleForTesting final State mDeleteIkeLocalDelete = new DeleteIkeLocalDelete(); // TODO: Add InfoLocal. - // Testing constructor + /** Constructor for testing. */ @VisibleForTesting - IkeSessionStateMachine( + public IkeSessionStateMachine( Looper looper, Context context, IpSecManager ipSecManager, @@ -435,8 +435,8 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { start(); } - /** Package private constructor */ - IkeSessionStateMachine( + /** Construct an instance of IkeSessionStateMachine. */ + public IkeSessionStateMachine( Looper looper, Context context, IpSecManager ipSecManager, @@ -498,11 +498,13 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { } } - void openSession() { + /** Initiates IKE setup procedure. */ + public void openSession() { sendMessage(CMD_LOCAL_REQUEST_CREATE_IKE, new LocalRequest(CMD_LOCAL_REQUEST_CREATE_IKE)); } - void openChildSession( + /** Schedules a Create Child procedure. */ + public void openChildSession( ChildSessionOptions childSessionOptions, ChildSessionCallback childSessionCallback) { if (childSessionCallback == null) { throw new IllegalArgumentException("Child Session Callback must be provided"); @@ -520,7 +522,8 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { CMD_LOCAL_REQUEST_CREATE_CHILD, childSessionCallback, childSessionOptions)); } - void closeChildSession(ChildSessionCallback childSessionCallback) { + /** Schedules a Delete Child procedure. */ + public void closeChildSession(ChildSessionCallback childSessionCallback) { if (childSessionCallback == null) { throw new IllegalArgumentException("Child Session Callback must be provided"); } @@ -534,11 +537,13 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { new ChildLocalRequest(CMD_LOCAL_REQUEST_DELETE_CHILD, childSessionCallback, null)); } - void closeSession() { + /** Initiates Delete IKE procedure. */ + public void closeSession() { sendMessage(CMD_LOCAL_REQUEST_DELETE_IKE, new LocalRequest(CMD_LOCAL_REQUEST_DELETE_IKE)); } - void killSession() { + /** Forcibly close IKE Session. */ + public void killSession() { // TODO: b/142977160 Support closing IKE Sesison immediately. } @@ -2308,7 +2313,8 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { } /** CreateIkeLocalIkeInit represents state when IKE library initiates IKE_INIT exchange. */ - class CreateIkeLocalIkeInit extends BusyState { + @VisibleForTesting + public class CreateIkeLocalIkeInit extends BusyState { private IkeSecurityParameterIndex mLocalIkeSpiResource; private IkeSecurityParameterIndex mRemoteIkeSpiResource; private Retransmitter mRetransmitter; @@ -2957,7 +2963,7 @@ public class IkeSessionStateMachine extends AbstractSessionStateMachine { + " notify type: " + notifyPayload.notifyType); } - + break; default: logw( "Received unexpected payload in IKE AUTH response. Payload" diff --git a/src/java/com/android/ike/ikev2/SaProposal.java b/src/java/com/android/ike/ikev2/SaProposal.java index b012ea06..6076590e 100644 --- a/src/java/com/android/ike/ikev2/SaProposal.java +++ b/src/java/com/android/ike/ikev2/SaProposal.java @@ -192,18 +192,15 @@ public abstract class SaProposal { return mProtocolId; } - /*Package private*/ - EncryptionTransform[] getEncryptionTransforms() { + public EncryptionTransform[] getEncryptionTransforms() { return mEncryptionAlgorithms; } - /*Package private*/ - IntegrityTransform[] getIntegrityTransforms() { + public IntegrityTransform[] getIntegrityTransforms() { return mIntegrityAlgorithms; } - /*Package private*/ - DhGroupTransform[] getDhGroupTransforms() { + public DhGroupTransform[] getDhGroupTransforms() { return mDhGroups; } diff --git a/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java b/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java index 541930eb..c207acc4 100644 --- a/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java +++ b/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java @@ -54,8 +54,7 @@ public final class TunnelModeChildSessionOptions extends ChildSessionOptions { mConfigRequests = configRequests; } - /** Package private */ - ConfigAttribute[] getConfigurationRequests() { + public ConfigAttribute[] getConfigurationRequests() { return mConfigRequests; } 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 819c3280..74b4003f 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionStateMachineTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/IkeSessionStateMachineTest.java @@ -713,7 +713,7 @@ public final class IkeSessionStateMachineTest { return ikeSession; } - static IkeSaProposal buildSaProposal() throws Exception { + public static IkeSaProposal buildSaProposal() throws Exception { return new IkeSaProposal.Builder() .addEncryptionAlgorithm( SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, SaProposal.KEY_LEN_AES_128) -- cgit v1.2.3 From e8da20d0f53fa8241d9195ae14b4434fe9b8e1e8 Mon Sep 17 00:00:00 2001 From: evitayan Date: Wed, 30 Oct 2019 14:36:17 -0700 Subject: Move API and impl to separate packages This commit - Moves API and implementation to separate packages so that later we can expose the API package only. - Also moves tests accordingly Bug: 143983419 Test: atest FrameworksIkeTests(all tests passed) Change-Id: I53cf15caefb09aabaeefd0167d8daeb23e5e571f --- src/java/android/net/eap/EapSessionConfig.java | 234 ++ .../android/net/ipsec/ike/ChildSaProposal.java | 171 + .../net/ipsec/ike/ChildSessionCallback.java | 66 + .../net/ipsec/ike/ChildSessionConfiguration.java | 130 + .../android/net/ipsec/ike/ChildSessionOptions.java | 119 + .../net/ipsec/ike/IkeFqdnIdentification.java | 76 + .../android/net/ipsec/ike/IkeIdentification.java | 80 + .../net/ipsec/ike/IkeIpv4AddrIdentification.java | 78 + .../net/ipsec/ike/IkeIpv6AddrIdentification.java | 78 + .../net/ipsec/ike/IkeKeyIdIdentification.java | 63 + src/java/android/net/ipsec/ike/IkeManager.java | 94 + .../net/ipsec/ike/IkeRfc822AddrIdentification.java | 76 + src/java/android/net/ipsec/ike/IkeSaProposal.java | 209 + src/java/android/net/ipsec/ike/IkeSession.java | 190 + .../android/net/ipsec/ike/IkeSessionCallback.java | 57 + .../net/ipsec/ike/IkeSessionConfiguration.java | 59 + .../android/net/ipsec/ike/IkeSessionOptions.java | 416 ++ .../android/net/ipsec/ike/IkeTrafficSelector.java | 373 ++ src/java/android/net/ipsec/ike/SaProposal.java | 386 ++ .../ike/TransportModeChildSessionOptions.java | 67 + .../ipsec/ike/TunnelModeChildSessionOptions.java | 260 ++ .../net/ipsec/ike/exceptions/IkeException.java | 47 + .../ipsec/ike/exceptions/IkeInternalException.java | 43 + .../ipsec/ike/exceptions/IkeProtocolException.java | 182 + .../com/android/ike/crypto/KeyGenerationUtils.java | 81 - src/java/com/android/ike/eap/EapAuthenticator.java | 176 - src/java/com/android/ike/eap/EapResult.java | 112 - src/java/com/android/ike/eap/EapSessionConfig.java | 234 -- src/java/com/android/ike/eap/IEapCallback.java | 56 - .../com/android/ike/eap/crypto/Fips186_2Prf.java | 111 - .../ike/eap/crypto/HmacSha256ByteSigner.java | 56 - .../com/android/ike/eap/crypto/ParityBitUtil.java | 81 - .../EapInvalidPacketLengthException.java | 47 - .../eap/exceptions/EapInvalidRequestException.java | 44 - .../ike/eap/exceptions/EapSilentException.java | 49 - .../eap/exceptions/InvalidEapCodeException.java | 36 - .../exceptions/InvalidEapResponseException.java | 34 - .../exceptions/UnsupportedEapTypeException.java | 53 - .../mschapv2/EapMsChapV2ParsingException.java | 42 - .../EapAkaInvalidAuthenticationResponse.java | 44 - .../EapSimAkaAuthenticationFailureException.java | 44 - .../EapSimAkaIdentityUnavailableException.java | 46 - .../simaka/EapSimAkaInvalidAtPaddingException.java | 51 - .../simaka/EapSimAkaInvalidAttributeException.java | 46 - .../simaka/EapSimAkaInvalidLengthException.java | 46 - .../EapSimAkaUnsupportedAttributeException.java | 51 - .../simaka/EapSimInvalidAtRandException.java | 49 - .../simaka/EapSimInvalidTypeDataException.java | 44 - src/java/com/android/ike/eap/message/EapData.java | 193 - .../com/android/ike/eap/message/EapMessage.java | 252 -- .../eap/message/mschapv2/EapMsChapV2TypeData.java | 600 --- .../eap/message/simaka/EapAkaAttributeFactory.java | 95 - .../simaka/EapAkaPrimeAttributeFactory.java | 77 - .../eap/message/simaka/EapAkaPrimeTypeData.java | 95 - .../ike/eap/message/simaka/EapAkaTypeData.java | 137 - .../ike/eap/message/simaka/EapSimAkaAttribute.java | 1162 ------ .../message/simaka/EapSimAkaAttributeFactory.java | 130 - .../ike/eap/message/simaka/EapSimAkaTypeData.java | 205 - .../eap/message/simaka/EapSimAttributeFactory.java | 87 - .../ike/eap/message/simaka/EapSimTypeData.java | 125 - .../eap/statemachine/EapAkaMethodStateMachine.java | 612 --- .../EapAkaPrimeMethodStateMachine.java | 336 -- .../eap/statemachine/EapMethodStateMachine.java | 105 - .../EapMsChapV2MethodStateMachine.java | 672 ---- .../statemachine/EapSimAkaMethodStateMachine.java | 355 -- .../eap/statemachine/EapSimMethodStateMachine.java | 604 --- .../ike/eap/statemachine/EapStateMachine.java | 371 -- .../ike/ikev2/AbstractSessionStateMachine.java | 199 - .../com/android/ike/ikev2/ChildSaProposal.java | 171 - .../android/ike/ikev2/ChildSessionCallback.java | 67 - .../ike/ikev2/ChildSessionConfiguration.java | 130 - .../com/android/ike/ikev2/ChildSessionOptions.java | 120 - .../ike/ikev2/ChildSessionStateMachine.java | 2260 ----------- .../ike/ikev2/ChildSessionStateMachineFactory.java | 93 - src/java/com/android/ike/ikev2/IkeDhParams.java | 43 - .../ike/ikev2/IkeEapAuthenticatorFactory.java | 40 - .../android/ike/ikev2/IkeFqdnIdentification.java | 76 - .../com/android/ike/ikev2/IkeIdentification.java | 80 - .../ike/ikev2/IkeIpv4AddrIdentification.java | 78 - .../ike/ikev2/IkeIpv6AddrIdentification.java | 78 - .../android/ike/ikev2/IkeKeyIdIdentification.java | 63 - .../ike/ikev2/IkeLocalRequestScheduler.java | 116 - src/java/com/android/ike/ikev2/IkeManager.java | 94 - .../ike/ikev2/IkeRfc822AddrIdentification.java | 76 - src/java/com/android/ike/ikev2/IkeSaProposal.java | 209 - src/java/com/android/ike/ikev2/IkeSession.java | 189 - .../com/android/ike/ikev2/IkeSessionCallback.java | 58 - .../android/ike/ikev2/IkeSessionConfiguration.java | 59 - .../com/android/ike/ikev2/IkeSessionOptions.java | 416 -- .../android/ike/ikev2/IkeSessionStateMachine.java | 4229 ------------------- src/java/com/android/ike/ikev2/IkeSocket.java | 282 -- .../com/android/ike/ikev2/IkeTrafficSelector.java | 373 -- src/java/com/android/ike/ikev2/SaProposal.java | 386 -- src/java/com/android/ike/ikev2/SaRecord.java | 1098 ----- .../ikev2/TransportModeChildSessionOptions.java | 67 - .../ike/ikev2/TunnelModeChildSessionOptions.java | 260 -- .../com/android/ike/ikev2/crypto/IkeCipher.java | 178 - .../ike/ikev2/crypto/IkeCombinedModeCipher.java | 210 - .../com/android/ike/ikev2/crypto/IkeCrypto.java | 57 - src/java/com/android/ike/ikev2/crypto/IkeMac.java | 93 - .../android/ike/ikev2/crypto/IkeMacIntegrity.java | 189 - .../com/android/ike/ikev2/crypto/IkeMacPrf.java | 151 - .../ike/ikev2/crypto/IkeNormalModeCipher.java | 125 - .../exceptions/AuthenticationFailedException.java | 60 - .../android/ike/ikev2/exceptions/IkeException.java | 47 - .../ike/ikev2/exceptions/IkeInternalException.java | 43 - .../ike/ikev2/exceptions/IkeProtocolException.java | 182 - .../ike/ikev2/exceptions/InvalidKeException.java | 62 - .../exceptions/InvalidMajorVersionException.java | 61 - .../exceptions/InvalidMessageIdException.java | 64 - .../ikev2/exceptions/InvalidSyntaxException.java | 71 - .../exceptions/NoValidProposalChosenException.java | 63 - .../exceptions/TemporaryFailureException.java | 50 - .../ikev2/exceptions/TsUnacceptableException.java | 46 - .../UnrecognizedIkeProtocolException.java | 39 - .../UnsupportedCriticalPayloadException.java | 74 - .../ikev2/message/IkeAuthDigitalSignPayload.java | 265 -- .../android/ike/ikev2/message/IkeAuthPayload.java | 128 - .../ike/ikev2/message/IkeAuthPskPayload.java | 141 - .../android/ike/ikev2/message/IkeCertPayload.java | 175 - .../ike/ikev2/message/IkeCertX509CertPayload.java | 104 - .../ike/ikev2/message/IkeConfigPayload.java | 767 ---- .../ike/ikev2/message/IkeDeletePayload.java | 176 - .../android/ike/ikev2/message/IkeEapPayload.java | 93 - .../ike/ikev2/message/IkeEncryptedPayloadBody.java | 389 -- .../com/android/ike/ikev2/message/IkeHeader.java | 244 -- .../android/ike/ikev2/message/IkeIdPayload.java | 166 - .../ike/ikev2/message/IkeInformationalPayload.java | 28 - .../android/ike/ikev2/message/IkeKePayload.java | 272 -- .../com/android/ike/ikev2/message/IkeMessage.java | 980 ----- .../android/ike/ikev2/message/IkeNoncePayload.java | 107 - .../ike/ikev2/message/IkeNotifyPayload.java | 462 --- .../com/android/ike/ikev2/message/IkePayload.java | 252 -- .../ike/ikev2/message/IkePayloadFactory.java | 244 -- .../android/ike/ikev2/message/IkeSaPayload.java | 1773 -------- .../android/ike/ikev2/message/IkeSkPayload.java | 207 - .../android/ike/ikev2/message/IkeSkfPayload.java | 175 - .../android/ike/ikev2/message/IkeTsPayload.java | 159 - .../ike/ikev2/message/IkeUnsupportedPayload.java | 71 - .../ike/ikev2/message/IkeVendorPayload.java | 76 - .../android/ike/ikev2/utils/FdEventsReader.java | 270 -- .../com/android/ike/ikev2/utils/PacketReader.java | 66 - .../com/android/ike/ikev2/utils/Retransmitter.java | 139 - .../com/android/ike/utils/BigIntegerUtils.java | 70 - src/java/com/android/ike/utils/Log.java | 284 -- .../com/android/ike/utils/SimpleStateMachine.java | 85 - .../internal/net/crypto/KeyGenerationUtils.java | 81 + .../android/internal/net/eap/EapAuthenticator.java | 177 + .../com/android/internal/net/eap/EapResult.java | 112 + .../com/android/internal/net/eap/IEapCallback.java | 56 + .../internal/net/eap/crypto/Fips186_2Prf.java | 111 + .../net/eap/crypto/HmacSha256ByteSigner.java | 56 + .../internal/net/eap/crypto/ParityBitUtil.java | 81 + .../EapInvalidPacketLengthException.java | 47 + .../eap/exceptions/EapInvalidRequestException.java | 44 + .../net/eap/exceptions/EapSilentException.java | 49 + .../eap/exceptions/InvalidEapCodeException.java | 36 + .../exceptions/InvalidEapResponseException.java | 34 + .../exceptions/UnsupportedEapTypeException.java | 53 + .../mschapv2/EapMsChapV2ParsingException.java | 42 + .../EapAkaInvalidAuthenticationResponse.java | 44 + .../EapSimAkaAuthenticationFailureException.java | 44 + .../EapSimAkaIdentityUnavailableException.java | 46 + .../simaka/EapSimAkaInvalidAtPaddingException.java | 51 + .../simaka/EapSimAkaInvalidAttributeException.java | 46 + .../simaka/EapSimAkaInvalidLengthException.java | 46 + .../EapSimAkaUnsupportedAttributeException.java | 51 + .../simaka/EapSimInvalidAtRandException.java | 49 + .../simaka/EapSimInvalidTypeDataException.java | 44 + .../android/internal/net/eap/message/EapData.java | 193 + .../internal/net/eap/message/EapMessage.java | 252 ++ .../eap/message/mschapv2/EapMsChapV2TypeData.java | 600 +++ .../eap/message/simaka/EapAkaAttributeFactory.java | 95 + .../simaka/EapAkaPrimeAttributeFactory.java | 77 + .../eap/message/simaka/EapAkaPrimeTypeData.java | 95 + .../net/eap/message/simaka/EapAkaTypeData.java | 137 + .../net/eap/message/simaka/EapSimAkaAttribute.java | 1162 ++++++ .../message/simaka/EapSimAkaAttributeFactory.java | 130 + .../net/eap/message/simaka/EapSimAkaTypeData.java | 205 + .../eap/message/simaka/EapSimAttributeFactory.java | 87 + .../net/eap/message/simaka/EapSimTypeData.java | 125 + .../eap/statemachine/EapAkaMethodStateMachine.java | 612 +++ .../EapAkaPrimeMethodStateMachine.java | 336 ++ .../eap/statemachine/EapMethodStateMachine.java | 105 + .../EapMsChapV2MethodStateMachine.java | 673 ++++ .../statemachine/EapSimAkaMethodStateMachine.java | 355 ++ .../eap/statemachine/EapSimMethodStateMachine.java | 604 +++ .../net/eap/statemachine/EapStateMachine.java | 371 ++ .../net/ipsec/ike/AbstractSessionStateMachine.java | 199 + .../net/ipsec/ike/ChildSessionStateMachine.java | 2268 +++++++++++ .../ipsec/ike/ChildSessionStateMachineFactory.java | 95 + .../internal/net/ipsec/ike/IkeDhParams.java | 43 + .../net/ipsec/ike/IkeEapAuthenticatorFactory.java | 40 + .../net/ipsec/ike/IkeLocalRequestScheduler.java | 119 + .../net/ipsec/ike/IkeSessionStateMachine.java | 4235 ++++++++++++++++++++ .../android/internal/net/ipsec/ike/IkeSocket.java | 281 ++ .../android/internal/net/ipsec/ike/SaRecord.java | 1098 +++++ .../internal/net/ipsec/ike/crypto/IkeCipher.java | 178 + .../ipsec/ike/crypto/IkeCombinedModeCipher.java | 209 + .../internal/net/ipsec/ike/crypto/IkeCrypto.java | 57 + .../internal/net/ipsec/ike/crypto/IkeMac.java | 93 + .../net/ipsec/ike/crypto/IkeMacIntegrity.java | 189 + .../internal/net/ipsec/ike/crypto/IkeMacPrf.java | 152 + .../net/ipsec/ike/crypto/IkeNormalModeCipher.java | 124 + .../exceptions/AuthenticationFailedException.java | 64 + .../ipsec/ike/exceptions/InvalidKeException.java | 66 + .../exceptions/InvalidMajorVersionException.java | 65 + .../ike/exceptions/InvalidMessageIdException.java | 68 + .../ike/exceptions/InvalidSyntaxException.java | 73 + .../exceptions/NoValidProposalChosenException.java | 67 + .../ike/exceptions/TemporaryFailureException.java | 54 + .../ike/exceptions/TsUnacceptableException.java | 50 + .../UnrecognizedIkeProtocolException.java | 41 + .../UnsupportedCriticalPayloadException.java | 78 + .../ike/message/IkeAuthDigitalSignPayload.java | 265 ++ .../net/ipsec/ike/message/IkeAuthPayload.java | 128 + .../net/ipsec/ike/message/IkeAuthPskPayload.java | 141 + .../net/ipsec/ike/message/IkeCertPayload.java | 175 + .../ipsec/ike/message/IkeCertX509CertPayload.java | 105 + .../net/ipsec/ike/message/IkeConfigPayload.java | 767 ++++ .../net/ipsec/ike/message/IkeDeletePayload.java | 177 + .../net/ipsec/ike/message/IkeEapPayload.java | 93 + .../ipsec/ike/message/IkeEncryptedPayloadBody.java | 390 ++ .../internal/net/ipsec/ike/message/IkeHeader.java | 244 ++ .../net/ipsec/ike/message/IkeIdPayload.java | 167 + .../ipsec/ike/message/IkeInformationalPayload.java | 28 + .../net/ipsec/ike/message/IkeKePayload.java | 272 ++ .../internal/net/ipsec/ike/message/IkeMessage.java | 981 +++++ .../net/ipsec/ike/message/IkeNoncePayload.java | 108 + .../net/ipsec/ike/message/IkeNotifyPayload.java | 462 +++ .../internal/net/ipsec/ike/message/IkePayload.java | 252 ++ .../net/ipsec/ike/message/IkePayloadFactory.java | 244 ++ .../net/ipsec/ike/message/IkeSaPayload.java | 1773 ++++++++ .../net/ipsec/ike/message/IkeSkPayload.java | 207 + .../net/ipsec/ike/message/IkeSkfPayload.java | 175 + .../net/ipsec/ike/message/IkeTsPayload.java | 160 + .../ipsec/ike/message/IkeUnsupportedPayload.java | 71 + .../net/ipsec/ike/message/IkeVendorPayload.java | 76 + .../net/ipsec/ike/utils/FdEventsReader.java | 270 ++ .../internal/net/ipsec/ike/utils/PacketReader.java | 66 + .../net/ipsec/ike/utils/Retransmitter.java | 139 + .../internal/net/utils/BigIntegerUtils.java | 70 + src/java/com/android/internal/net/utils/Log.java | 284 ++ .../internal/net/utils/SimpleStateMachine.java | 85 + .../java/android/net/eap/EapSessionConfigTest.java | 115 + .../ipsec/ike/ChildSessionConfigurationTest.java | 164 + .../net/ipsec/ike/ChildSessionOptionsTest.java | 54 + .../net/ipsec/ike/IkeSessionOptionsTest.java | 258 ++ .../java/android/net/ipsec/ike/IkeSessionTest.java | 162 + .../net/ipsec/ike/IkeTrafficSelectorTest.java | 312 ++ .../java/android/net/ipsec/ike/SaProposalTest.java | 321 ++ .../ike/TunnelModeChildSessionOptionsTest.java | 229 ++ .../ike/exceptions/IkeProtocolExceptionTest.java | 58 + .../src/java/com/android/ike/TestUtils.java | 113 - .../java/com/android/ike/eap/EapAkaPrimeTest.java | 381 -- .../src/java/com/android/ike/eap/EapAkaTest.java | 331 -- .../com/android/ike/eap/EapAuthenticatorTest.java | 256 -- .../src/java/com/android/ike/eap/EapErrorTest.java | 33 - .../com/android/ike/eap/EapMethodEndToEndTest.java | 90 - .../java/com/android/ike/eap/EapMsChapV2Test.java | 171 - .../java/com/android/ike/eap/EapResponseTest.java | 70 - .../com/android/ike/eap/EapSessionConfigTest.java | 115 - .../src/java/com/android/ike/eap/EapSimTest.java | 297 -- .../java/com/android/ike/eap/EapSuccessTest.java | 54 - .../src/java/com/android/ike/eap/EapTestUtils.java | 54 - .../android/ike/eap/crypto/Fips186_2PrfTest.java | 67 - .../ike/eap/crypto/HmacSha256ByteSignerTest.java | 93 - .../android/ike/eap/crypto/ParityBitUtilTest.java | 65 - .../com/android/ike/eap/message/EapDataTest.java | 95 - .../android/ike/eap/message/EapMessageTest.java | 182 - .../ike/eap/message/EapTestMessageDefinitions.java | 327 -- .../mschapv2/EapMsChapV2ChallengeRequestTest.java | 120 - .../mschapv2/EapMsChapV2ChallengeResponseTest.java | 109 - .../mschapv2/EapMsChapV2FailureRequestTest.java | 172 - .../mschapv2/EapMsChapV2FailureResponseTest.java | 43 - .../mschapv2/EapMsChapV2PacketDefinitions.java | 284 -- .../mschapv2/EapMsChapV2SuccessRequestTest.java | 187 - .../mschapv2/EapMsChapV2SuccessResponseTest.java | 43 - .../message/mschapv2/EapMsChapV2TypeDataTest.java | 154 - .../message/simaka/EapAkaPrimeTypeDataTest.java | 142 - .../ike/eap/message/simaka/EapAkaTypeDataTest.java | 176 - .../simaka/EapSimAkaAttributeFactoryTest.java | 94 - .../ike/eap/message/simaka/EapSimTypeDataTest.java | 176 - .../eap/message/simaka/attributes/AtAutnTest.java | 77 - .../eap/message/simaka/attributes/AtAutsTest.java | 77 - .../message/simaka/attributes/AtBiddingTest.java | 99 - .../simaka/attributes/AtClientErrorCodeTest.java | 83 - .../message/simaka/attributes/AtCounterTest.java | 122 - .../eap/message/simaka/attributes/AtIdReqTest.java | 149 - .../message/simaka/attributes/AtIdentityTest.java | 85 - .../message/simaka/attributes/AtKdfInputTest.java | 78 - .../eap/message/simaka/attributes/AtKdfTest.java | 78 - .../eap/message/simaka/attributes/AtMacTest.java | 110 - .../message/simaka/attributes/AtNonceMtTest.java | 91 - .../message/simaka/attributes/AtNonceSTest.java | 92 - .../simaka/attributes/AtNotificationTest.java | 109 - .../message/simaka/attributes/AtPaddingTest.java | 81 - .../message/simaka/attributes/AtRandAkaTest.java | 77 - .../message/simaka/attributes/AtRandSimTest.java | 101 - .../eap/message/simaka/attributes/AtResTest.java | 117 - .../simaka/attributes/AtSelectedVersionTest.java | 83 - .../simaka/attributes/AtVersionListTest.java | 85 - .../simaka/attributes/EapSimAkaAttributeTest.java | 53 - .../attributes/EapTestAttributeDefinitions.java | 120 - .../ike/eap/statemachine/CreatedStateTest.java | 79 - .../eap/statemachine/EapAkaChallengeStateTest.java | 430 -- .../eap/statemachine/EapAkaCreatedStateTest.java | 110 - .../eap/statemachine/EapAkaIdentityStateTest.java | 161 - .../statemachine/EapAkaMethodStateMachineTest.java | 152 - .../EapAkaPrimeChallengeStateTest.java | 353 -- .../statemachine/EapAkaPrimeCreatedStateTest.java | 85 - .../statemachine/EapAkaPrimeIdentityStateTest.java | 96 - .../EapAkaPrimeMethodStateMachineTest.java | 74 - .../ike/eap/statemachine/EapAkaPrimeStateTest.java | 100 - .../ike/eap/statemachine/EapAkaPrimeTest.java | 78 - .../ike/eap/statemachine/EapAkaStateTest.java | 147 - .../EapMsChapV2AwaitingEapFailureStateTest.java | 29 - .../EapMsChapV2AwaitingEapSuccessStateTest.java | 54 - .../EapMsChapV2ChallengeStateTest.java | 104 - .../statemachine/EapMsChapV2CreatedStateTest.java | 80 - .../EapMsChapV2MethodStateMachineTest.java | 181 - .../ike/eap/statemachine/EapMsChapV2StateTest.java | 99 - .../EapMsChapV2ValidateAuthenticatorStateTest.java | 173 - .../EapSimAkaMethodStateMachineTest.java | 475 --- .../eap/statemachine/EapSimChallengeStateTest.java | 356 -- .../eap/statemachine/EapSimCreatedStateTest.java | 112 - .../statemachine/EapSimMethodStateMachineTest.java | 152 - .../ike/eap/statemachine/EapSimStartStateTest.java | 254 -- .../ike/eap/statemachine/EapSimStateTest.java | 149 - .../ike/eap/statemachine/EapStateMachineTest.java | 81 - .../android/ike/eap/statemachine/EapStateTest.java | 128 - .../ike/eap/statemachine/IdentityStateTest.java | 101 - .../ike/eap/statemachine/MethodStateTest.java | 203 - .../ike/ikev2/ChildSessionConfigurationTest.java | 164 - .../android/ike/ikev2/ChildSessionOptionsTest.java | 54 - .../ike/ikev2/ChildSessionStateMachineTest.java | 1638 -------- .../ike/ikev2/IkeLocalRequestSchedulerTest.java | 130 - .../android/ike/ikev2/IkeSessionOptionsTest.java | 258 -- .../ike/ikev2/IkeSessionStateMachineTest.java | 4025 ------------------- .../java/com/android/ike/ikev2/IkeSessionTest.java | 160 - .../java/com/android/ike/ikev2/IkeSocketTest.java | 385 -- .../android/ike/ikev2/IkeTrafficSelectorTest.java | 312 -- .../java/com/android/ike/ikev2/SaProposalTest.java | 321 -- .../java/com/android/ike/ikev2/SaRecordTest.java | 335 -- .../ikev2/TunnelModeChildSessionOptionsTest.java | 229 -- .../ikev2/crypto/IkeCombinedModeCipherTest.java | 160 - .../ike/ikev2/crypto/IkeMacIntegrityTest.java | 128 - .../android/ike/ikev2/crypto/IkeMacPrfTest.java | 186 - .../ike/ikev2/crypto/IkeNormalModeCipherTest.java | 164 - .../ikev2/exceptions/IkeProtocolExceptionTest.java | 56 - .../message/IkeAuthDigitalSignPayloadTest.java | 160 - .../ike/ikev2/message/IkeAuthPayloadTest.java | 132 - .../ike/ikev2/message/IkeAuthPskPayloadTest.java | 143 - .../ike/ikev2/message/IkeCertPayloadTest.java | 154 - .../ikev2/message/IkeCertX509CertPayloadTest.java | 147 - .../ike/ikev2/message/IkeConfigPayloadTest.java | 631 --- .../ike/ikev2/message/IkeDeletePayloadTest.java | 264 -- .../ike/ikev2/message/IkeEapPayloadTest.java | 68 - .../ikev2/message/IkeEncryptedPayloadBodyTest.java | 488 --- .../android/ike/ikev2/message/IkeHeaderTest.java | 140 - .../ike/ikev2/message/IkeIdPayloadTest.java | 209 - .../ike/ikev2/message/IkeKePayloadTest.java | 199 - .../android/ike/ikev2/message/IkeMessageTest.java | 934 ----- .../ike/ikev2/message/IkeNoncePayloadTest.java | 49 - .../ike/ikev2/message/IkeNotifyPayloadTest.java | 248 -- .../ike/ikev2/message/IkeSaPayloadTest.java | 927 ----- .../ike/ikev2/message/IkeSkPayloadTest.java | 107 - .../ike/ikev2/message/IkeSkfPayloadTest.java | 200 - .../android/ike/ikev2/message/IkeTestUtils.java | 71 - .../ike/ikev2/message/IkeTsPayloadTest.java | 142 - .../com/android/ike/ikev2/testutils/CertUtils.java | 63 - .../ike/ikev2/testutils/MockIpSecTestUtils.java | 91 - .../android/ike/ikev2/utils/RetransmitterTest.java | 129 - .../com/android/ike/utils/BigIntegerUtilsTest.java | 49 - .../src/java/com/android/ike/utils/LogTest.java | 60 - .../android/ike/utils/SimpleStateMachineTest.java | 96 - .../java/com/android/internal/net/TestUtils.java | 113 + .../android/internal/net/eap/EapAkaPrimeTest.java | 382 ++ .../com/android/internal/net/eap/EapAkaTest.java | 332 ++ .../internal/net/eap/EapAuthenticatorTest.java | 256 ++ .../com/android/internal/net/eap/EapErrorTest.java | 33 + .../internal/net/eap/EapMethodEndToEndTest.java | 91 + .../android/internal/net/eap/EapMsChapV2Test.java | 173 + .../android/internal/net/eap/EapResponseTest.java | 70 + .../com/android/internal/net/eap/EapSimTest.java | 298 ++ .../android/internal/net/eap/EapSuccessTest.java | 54 + .../com/android/internal/net/eap/EapTestUtils.java | 56 + .../internal/net/eap/crypto/Fips186_2PrfTest.java | 67 + .../net/eap/crypto/HmacSha256ByteSignerTest.java | 93 + .../internal/net/eap/crypto/ParityBitUtilTest.java | 65 + .../internal/net/eap/message/EapDataTest.java | 95 + .../internal/net/eap/message/EapMessageTest.java | 182 + .../net/eap/message/EapTestMessageDefinitions.java | 327 ++ .../mschapv2/EapMsChapV2ChallengeRequestTest.java | 120 + .../mschapv2/EapMsChapV2ChallengeResponseTest.java | 109 + .../mschapv2/EapMsChapV2FailureRequestTest.java | 172 + .../mschapv2/EapMsChapV2FailureResponseTest.java | 43 + .../mschapv2/EapMsChapV2PacketDefinitions.java | 284 ++ .../mschapv2/EapMsChapV2SuccessRequestTest.java | 187 + .../mschapv2/EapMsChapV2SuccessResponseTest.java | 43 + .../message/mschapv2/EapMsChapV2TypeDataTest.java | 154 + .../message/simaka/EapAkaPrimeTypeDataTest.java | 142 + .../net/eap/message/simaka/EapAkaTypeDataTest.java | 176 + .../simaka/EapSimAkaAttributeFactoryTest.java | 94 + .../net/eap/message/simaka/EapSimTypeDataTest.java | 176 + .../eap/message/simaka/attributes/AtAutnTest.java | 77 + .../eap/message/simaka/attributes/AtAutsTest.java | 77 + .../message/simaka/attributes/AtBiddingTest.java | 99 + .../simaka/attributes/AtClientErrorCodeTest.java | 83 + .../message/simaka/attributes/AtCounterTest.java | 122 + .../eap/message/simaka/attributes/AtIdReqTest.java | 149 + .../message/simaka/attributes/AtIdentityTest.java | 85 + .../message/simaka/attributes/AtKdfInputTest.java | 78 + .../eap/message/simaka/attributes/AtKdfTest.java | 78 + .../eap/message/simaka/attributes/AtMacTest.java | 110 + .../message/simaka/attributes/AtNonceMtTest.java | 91 + .../message/simaka/attributes/AtNonceSTest.java | 92 + .../simaka/attributes/AtNotificationTest.java | 109 + .../message/simaka/attributes/AtPaddingTest.java | 81 + .../message/simaka/attributes/AtRandAkaTest.java | 77 + .../message/simaka/attributes/AtRandSimTest.java | 101 + .../eap/message/simaka/attributes/AtResTest.java | 117 + .../simaka/attributes/AtSelectedVersionTest.java | 83 + .../simaka/attributes/AtVersionListTest.java | 85 + .../simaka/attributes/EapSimAkaAttributeTest.java | 53 + .../attributes/EapTestAttributeDefinitions.java | 120 + .../net/eap/statemachine/CreatedStateTest.java | 79 + .../eap/statemachine/EapAkaChallengeStateTest.java | 430 ++ .../eap/statemachine/EapAkaCreatedStateTest.java | 110 + .../eap/statemachine/EapAkaIdentityStateTest.java | 161 + .../statemachine/EapAkaMethodStateMachineTest.java | 152 + .../EapAkaPrimeChallengeStateTest.java | 354 ++ .../statemachine/EapAkaPrimeCreatedStateTest.java | 85 + .../statemachine/EapAkaPrimeIdentityStateTest.java | 96 + .../EapAkaPrimeMethodStateMachineTest.java | 74 + .../net/eap/statemachine/EapAkaPrimeStateTest.java | 100 + .../net/eap/statemachine/EapAkaPrimeTest.java | 78 + .../net/eap/statemachine/EapAkaStateTest.java | 147 + .../EapMsChapV2AwaitingEapFailureStateTest.java | 29 + .../EapMsChapV2AwaitingEapSuccessStateTest.java | 54 + .../EapMsChapV2ChallengeStateTest.java | 104 + .../statemachine/EapMsChapV2CreatedStateTest.java | 80 + .../EapMsChapV2MethodStateMachineTest.java | 182 + .../net/eap/statemachine/EapMsChapV2StateTest.java | 100 + .../EapMsChapV2ValidateAuthenticatorStateTest.java | 173 + .../EapSimAkaMethodStateMachineTest.java | 475 +++ .../eap/statemachine/EapSimChallengeStateTest.java | 356 ++ .../eap/statemachine/EapSimCreatedStateTest.java | 111 + .../statemachine/EapSimMethodStateMachineTest.java | 152 + .../net/eap/statemachine/EapSimStartStateTest.java | 254 ++ .../net/eap/statemachine/EapSimStateTest.java | 149 + .../net/eap/statemachine/EapStateMachineTest.java | 81 + .../net/eap/statemachine/EapStateTest.java | 128 + .../net/eap/statemachine/IdentityStateTest.java | 101 + .../net/eap/statemachine/MethodStateTest.java | 204 + .../ipsec/ike/ChildSessionStateMachineTest.java | 1646 ++++++++ .../ipsec/ike/IkeLocalRequestSchedulerTest.java | 130 + .../net/ipsec/ike/IkeSessionStateMachineTest.java | 4036 +++++++++++++++++++ .../internal/net/ipsec/ike/IkeSocketTest.java | 385 ++ .../internal/net/ipsec/ike/SaRecordTest.java | 336 ++ .../ike/crypto/IkeCombinedModeCipherTest.java | 160 + .../net/ipsec/ike/crypto/IkeMacIntegrityTest.java | 128 + .../net/ipsec/ike/crypto/IkeMacPrfTest.java | 187 + .../ipsec/ike/crypto/IkeNormalModeCipherTest.java | 164 + .../ike/message/IkeAuthDigitalSignPayloadTest.java | 161 + .../net/ipsec/ike/message/IkeAuthPayloadTest.java | 133 + .../ipsec/ike/message/IkeAuthPskPayloadTest.java | 144 + .../net/ipsec/ike/message/IkeCertPayloadTest.java | 154 + .../ike/message/IkeCertX509CertPayloadTest.java | 147 + .../ipsec/ike/message/IkeConfigPayloadTest.java | 631 +++ .../ipsec/ike/message/IkeDeletePayloadTest.java | 264 ++ .../net/ipsec/ike/message/IkeEapPayloadTest.java | 68 + .../ike/message/IkeEncryptedPayloadBodyTest.java | 489 +++ .../net/ipsec/ike/message/IkeHeaderTest.java | 140 + .../net/ipsec/ike/message/IkeIdPayloadTest.java | 210 + .../net/ipsec/ike/message/IkeKePayloadTest.java | 200 + .../net/ipsec/ike/message/IkeMessageTest.java | 935 +++++ .../net/ipsec/ike/message/IkeNoncePayloadTest.java | 49 + .../ipsec/ike/message/IkeNotifyPayloadTest.java | 249 ++ .../net/ipsec/ike/message/IkeSaPayloadTest.java | 927 +++++ .../net/ipsec/ike/message/IkeSkPayloadTest.java | 108 + .../net/ipsec/ike/message/IkeSkfPayloadTest.java | 201 + .../net/ipsec/ike/message/IkeTestUtils.java | 71 + .../net/ipsec/ike/message/IkeTsPayloadTest.java | 143 + .../net/ipsec/ike/testutils/CertUtils.java | 63 + .../ipsec/ike/testutils/MockIpSecTestUtils.java | 91 + .../net/ipsec/ike/utils/RetransmitterTest.java | 129 + .../internal/net/utils/BigIntegerUtilsTest.java | 49 + .../com/android/internal/net/utils/LogTest.java | 60 + .../internal/net/utils/SimpleStateMachineTest.java | 96 + 490 files changed, 55259 insertions(+), 55152 deletions(-) create mode 100644 src/java/android/net/eap/EapSessionConfig.java create mode 100644 src/java/android/net/ipsec/ike/ChildSaProposal.java create mode 100644 src/java/android/net/ipsec/ike/ChildSessionCallback.java create mode 100644 src/java/android/net/ipsec/ike/ChildSessionConfiguration.java create mode 100644 src/java/android/net/ipsec/ike/ChildSessionOptions.java create mode 100644 src/java/android/net/ipsec/ike/IkeFqdnIdentification.java create mode 100644 src/java/android/net/ipsec/ike/IkeIdentification.java create mode 100644 src/java/android/net/ipsec/ike/IkeIpv4AddrIdentification.java create mode 100644 src/java/android/net/ipsec/ike/IkeIpv6AddrIdentification.java create mode 100644 src/java/android/net/ipsec/ike/IkeKeyIdIdentification.java create mode 100644 src/java/android/net/ipsec/ike/IkeManager.java create mode 100644 src/java/android/net/ipsec/ike/IkeRfc822AddrIdentification.java create mode 100644 src/java/android/net/ipsec/ike/IkeSaProposal.java create mode 100644 src/java/android/net/ipsec/ike/IkeSession.java create mode 100644 src/java/android/net/ipsec/ike/IkeSessionCallback.java create mode 100644 src/java/android/net/ipsec/ike/IkeSessionConfiguration.java create mode 100644 src/java/android/net/ipsec/ike/IkeSessionOptions.java create mode 100644 src/java/android/net/ipsec/ike/IkeTrafficSelector.java create mode 100644 src/java/android/net/ipsec/ike/SaProposal.java create mode 100644 src/java/android/net/ipsec/ike/TransportModeChildSessionOptions.java create mode 100644 src/java/android/net/ipsec/ike/TunnelModeChildSessionOptions.java create mode 100644 src/java/android/net/ipsec/ike/exceptions/IkeException.java create mode 100644 src/java/android/net/ipsec/ike/exceptions/IkeInternalException.java create mode 100644 src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java delete mode 100644 src/java/com/android/ike/crypto/KeyGenerationUtils.java delete mode 100644 src/java/com/android/ike/eap/EapAuthenticator.java delete mode 100644 src/java/com/android/ike/eap/EapResult.java delete mode 100644 src/java/com/android/ike/eap/EapSessionConfig.java delete mode 100644 src/java/com/android/ike/eap/IEapCallback.java delete mode 100644 src/java/com/android/ike/eap/crypto/Fips186_2Prf.java delete mode 100644 src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java delete mode 100644 src/java/com/android/ike/eap/crypto/ParityBitUtil.java delete mode 100644 src/java/com/android/ike/eap/exceptions/EapInvalidPacketLengthException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/EapInvalidRequestException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/EapSilentException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/InvalidEapCodeException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/InvalidEapResponseException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/UnsupportedEapTypeException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/mschapv2/EapMsChapV2ParsingException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapAkaInvalidAuthenticationResponse.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaAuthenticationFailureException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaIdentityUnavailableException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidAtPaddingException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidAttributeException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidLengthException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaUnsupportedAttributeException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapSimInvalidAtRandException.java delete mode 100644 src/java/com/android/ike/eap/exceptions/simaka/EapSimInvalidTypeDataException.java delete mode 100644 src/java/com/android/ike/eap/message/EapData.java delete mode 100644 src/java/com/android/ike/eap/message/EapMessage.java delete mode 100644 src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2TypeData.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapAkaAttributeFactory.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapAkaPrimeAttributeFactory.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapAkaPrimeTypeData.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapAkaTypeData.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapSimAkaAttribute.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapSimAkaAttributeFactory.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapSimAkaTypeData.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapSimAttributeFactory.java delete mode 100644 src/java/com/android/ike/eap/message/simaka/EapSimTypeData.java delete mode 100644 src/java/com/android/ike/eap/statemachine/EapAkaMethodStateMachine.java delete mode 100644 src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachine.java delete mode 100644 src/java/com/android/ike/eap/statemachine/EapMethodStateMachine.java delete mode 100644 src/java/com/android/ike/eap/statemachine/EapMsChapV2MethodStateMachine.java delete mode 100644 src/java/com/android/ike/eap/statemachine/EapSimAkaMethodStateMachine.java delete mode 100644 src/java/com/android/ike/eap/statemachine/EapSimMethodStateMachine.java delete mode 100644 src/java/com/android/ike/eap/statemachine/EapStateMachine.java delete mode 100644 src/java/com/android/ike/ikev2/AbstractSessionStateMachine.java delete mode 100644 src/java/com/android/ike/ikev2/ChildSaProposal.java delete mode 100644 src/java/com/android/ike/ikev2/ChildSessionCallback.java delete mode 100644 src/java/com/android/ike/ikev2/ChildSessionConfiguration.java delete mode 100644 src/java/com/android/ike/ikev2/ChildSessionOptions.java delete mode 100644 src/java/com/android/ike/ikev2/ChildSessionStateMachine.java delete mode 100644 src/java/com/android/ike/ikev2/ChildSessionStateMachineFactory.java delete mode 100644 src/java/com/android/ike/ikev2/IkeDhParams.java delete mode 100644 src/java/com/android/ike/ikev2/IkeEapAuthenticatorFactory.java delete mode 100644 src/java/com/android/ike/ikev2/IkeFqdnIdentification.java delete mode 100644 src/java/com/android/ike/ikev2/IkeIdentification.java delete mode 100644 src/java/com/android/ike/ikev2/IkeIpv4AddrIdentification.java delete mode 100644 src/java/com/android/ike/ikev2/IkeIpv6AddrIdentification.java delete mode 100644 src/java/com/android/ike/ikev2/IkeKeyIdIdentification.java delete mode 100644 src/java/com/android/ike/ikev2/IkeLocalRequestScheduler.java delete mode 100644 src/java/com/android/ike/ikev2/IkeManager.java delete mode 100644 src/java/com/android/ike/ikev2/IkeRfc822AddrIdentification.java delete mode 100644 src/java/com/android/ike/ikev2/IkeSaProposal.java delete mode 100644 src/java/com/android/ike/ikev2/IkeSession.java delete mode 100644 src/java/com/android/ike/ikev2/IkeSessionCallback.java delete mode 100644 src/java/com/android/ike/ikev2/IkeSessionConfiguration.java delete mode 100644 src/java/com/android/ike/ikev2/IkeSessionOptions.java delete mode 100644 src/java/com/android/ike/ikev2/IkeSessionStateMachine.java delete mode 100644 src/java/com/android/ike/ikev2/IkeSocket.java delete mode 100644 src/java/com/android/ike/ikev2/IkeTrafficSelector.java delete mode 100644 src/java/com/android/ike/ikev2/SaProposal.java delete mode 100644 src/java/com/android/ike/ikev2/SaRecord.java delete mode 100644 src/java/com/android/ike/ikev2/TransportModeChildSessionOptions.java delete mode 100644 src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java delete mode 100644 src/java/com/android/ike/ikev2/crypto/IkeCipher.java delete mode 100644 src/java/com/android/ike/ikev2/crypto/IkeCombinedModeCipher.java delete mode 100644 src/java/com/android/ike/ikev2/crypto/IkeCrypto.java delete mode 100644 src/java/com/android/ike/ikev2/crypto/IkeMac.java delete mode 100644 src/java/com/android/ike/ikev2/crypto/IkeMacIntegrity.java delete mode 100644 src/java/com/android/ike/ikev2/crypto/IkeMacPrf.java delete mode 100644 src/java/com/android/ike/ikev2/crypto/IkeNormalModeCipher.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/AuthenticationFailedException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/IkeException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/IkeInternalException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/IkeProtocolException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/InvalidKeException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/InvalidMajorVersionException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/InvalidMessageIdException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/InvalidSyntaxException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/NoValidProposalChosenException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/TemporaryFailureException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/TsUnacceptableException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/UnrecognizedIkeProtocolException.java delete mode 100644 src/java/com/android/ike/ikev2/exceptions/UnsupportedCriticalPayloadException.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeAuthPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeAuthPskPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeCertPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeCertX509CertPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeConfigPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeDeletePayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeEapPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeEncryptedPayloadBody.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeHeader.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeIdPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeInformationalPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeKePayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeMessage.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeNoncePayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeNotifyPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkePayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkePayloadFactory.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeSaPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeSkPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeSkfPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeTsPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeUnsupportedPayload.java delete mode 100644 src/java/com/android/ike/ikev2/message/IkeVendorPayload.java delete mode 100644 src/java/com/android/ike/ikev2/utils/FdEventsReader.java delete mode 100644 src/java/com/android/ike/ikev2/utils/PacketReader.java delete mode 100644 src/java/com/android/ike/ikev2/utils/Retransmitter.java delete mode 100644 src/java/com/android/ike/utils/BigIntegerUtils.java delete mode 100644 src/java/com/android/ike/utils/Log.java delete mode 100644 src/java/com/android/ike/utils/SimpleStateMachine.java create mode 100644 src/java/com/android/internal/net/crypto/KeyGenerationUtils.java create mode 100644 src/java/com/android/internal/net/eap/EapAuthenticator.java create mode 100644 src/java/com/android/internal/net/eap/EapResult.java create mode 100644 src/java/com/android/internal/net/eap/IEapCallback.java create mode 100644 src/java/com/android/internal/net/eap/crypto/Fips186_2Prf.java create mode 100644 src/java/com/android/internal/net/eap/crypto/HmacSha256ByteSigner.java create mode 100644 src/java/com/android/internal/net/eap/crypto/ParityBitUtil.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/EapInvalidPacketLengthException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/EapInvalidRequestException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/EapSilentException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/InvalidEapCodeException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/InvalidEapResponseException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/UnsupportedEapTypeException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/mschapv2/EapMsChapV2ParsingException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapAkaInvalidAuthenticationResponse.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapSimAkaAuthenticationFailureException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapSimAkaIdentityUnavailableException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapSimAkaInvalidAtPaddingException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapSimAkaInvalidAttributeException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapSimAkaInvalidLengthException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapSimAkaUnsupportedAttributeException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapSimInvalidAtRandException.java create mode 100644 src/java/com/android/internal/net/eap/exceptions/simaka/EapSimInvalidTypeDataException.java create mode 100644 src/java/com/android/internal/net/eap/message/EapData.java create mode 100644 src/java/com/android/internal/net/eap/message/EapMessage.java create mode 100644 src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2TypeData.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapAkaAttributeFactory.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeAttributeFactory.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeData.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeData.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapSimAkaAttribute.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapSimAkaAttributeFactory.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapSimAkaTypeData.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapSimAttributeFactory.java create mode 100644 src/java/com/android/internal/net/eap/message/simaka/EapSimTypeData.java create mode 100644 src/java/com/android/internal/net/eap/statemachine/EapAkaMethodStateMachine.java create mode 100644 src/java/com/android/internal/net/eap/statemachine/EapAkaPrimeMethodStateMachine.java create mode 100644 src/java/com/android/internal/net/eap/statemachine/EapMethodStateMachine.java create mode 100644 src/java/com/android/internal/net/eap/statemachine/EapMsChapV2MethodStateMachine.java create mode 100644 src/java/com/android/internal/net/eap/statemachine/EapSimAkaMethodStateMachine.java create mode 100644 src/java/com/android/internal/net/eap/statemachine/EapSimMethodStateMachine.java create mode 100644 src/java/com/android/internal/net/eap/statemachine/EapStateMachine.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/AbstractSessionStateMachine.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/ChildSessionStateMachine.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/ChildSessionStateMachineFactory.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/IkeDhParams.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/IkeEapAuthenticatorFactory.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/IkeLocalRequestScheduler.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/IkeSocket.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/SaRecord.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/crypto/IkeCipher.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/crypto/IkeCombinedModeCipher.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/crypto/IkeCrypto.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/crypto/IkeMac.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrity.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacPrf.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipher.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/AuthenticationFailedException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/InvalidKeException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/InvalidMajorVersionException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/InvalidMessageIdException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/InvalidSyntaxException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/NoValidProposalChosenException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/TemporaryFailureException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/TsUnacceptableException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/UnrecognizedIkeProtocolException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/exceptions/UnsupportedCriticalPayloadException.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeAuthDigitalSignPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeAuthPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeAuthPskPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeCertPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeCertX509CertPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeConfigPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeDeletePayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeEapPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeEncryptedPayloadBody.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeHeader.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeIdPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeInformationalPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeKePayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeMessage.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeNoncePayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeNotifyPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkePayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkePayloadFactory.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeSaPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeSkPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeSkfPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeTsPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeUnsupportedPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/message/IkeVendorPayload.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/utils/FdEventsReader.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/utils/PacketReader.java create mode 100644 src/java/com/android/internal/net/ipsec/ike/utils/Retransmitter.java create mode 100644 src/java/com/android/internal/net/utils/BigIntegerUtils.java create mode 100644 src/java/com/android/internal/net/utils/Log.java create mode 100644 src/java/com/android/internal/net/utils/SimpleStateMachine.java create mode 100644 tests/iketests/src/java/android/net/eap/EapSessionConfigTest.java create mode 100644 tests/iketests/src/java/android/net/ipsec/ike/ChildSessionConfigurationTest.java create mode 100644 tests/iketests/src/java/android/net/ipsec/ike/ChildSessionOptionsTest.java create mode 100644 tests/iketests/src/java/android/net/ipsec/ike/IkeSessionOptionsTest.java create mode 100644 tests/iketests/src/java/android/net/ipsec/ike/IkeSessionTest.java create mode 100644 tests/iketests/src/java/android/net/ipsec/ike/IkeTrafficSelectorTest.java create mode 100644 tests/iketests/src/java/android/net/ipsec/ike/SaProposalTest.java create mode 100644 tests/iketests/src/java/android/net/ipsec/ike/TunnelModeChildSessionOptionsTest.java create mode 100644 tests/iketests/src/java/android/net/ipsec/ike/exceptions/IkeProtocolExceptionTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/TestUtils.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapAkaPrimeTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapAkaTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapAuthenticatorTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapErrorTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapMethodEndToEndTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapMsChapV2Test.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapResponseTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapSessionConfigTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapSimTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapSuccessTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/EapTestUtils.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/crypto/Fips186_2PrfTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/crypto/HmacSha256ByteSignerTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/crypto/ParityBitUtilTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/EapDataTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/EapMessageTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2ChallengeRequestTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2ChallengeResponseTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2FailureRequestTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2FailureResponseTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2PacketDefinitions.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2SuccessRequestTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2SuccessResponseTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2TypeDataTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaPrimeTypeDataTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaTypeDataTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimAkaAttributeFactoryTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtAutnTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtAutsTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtBiddingTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtClientErrorCodeTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtCounterTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtIdReqTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtIdentityTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtKdfInputTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtKdfTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtMacTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtNonceMtTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtNonceSTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtNotificationTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtPaddingTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtRandAkaTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtRandSimTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtResTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtSelectedVersionTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/AtVersionListTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/EapSimAkaAttributeTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/message/simaka/attributes/EapTestAttributeDefinitions.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/CreatedStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaChallengeStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaCreatedStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaIdentityStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaMethodStateMachineTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeChallengeStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeCreatedStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeIdentityStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeMethodStateMachineTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaPrimeTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapAkaStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2AwaitingEapFailureStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2AwaitingEapSuccessStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2ChallengeStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2CreatedStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2MethodStateMachineTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2StateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapMsChapV2ValidateAuthenticatorStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimAkaMethodStateMachineTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimChallengeStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimCreatedStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimMethodStateMachineTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStartStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapSimStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapStateMachineTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/EapStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/IdentityStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/eap/statemachine/MethodStateTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/ChildSessionConfigurationTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/ChildSessionOptionsTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/ChildSessionStateMachineTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/IkeLocalRequestSchedulerTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/IkeSessionOptionsTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/IkeSessionStateMachineTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/IkeSessionTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/IkeSocketTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/IkeTrafficSelectorTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/SaProposalTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/SaRecordTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/crypto/IkeCombinedModeCipherTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/crypto/IkeMacIntegrityTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/crypto/IkeMacPrfTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/crypto/IkeNormalModeCipherTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/exceptions/IkeProtocolExceptionTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthDigitalSignPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeAuthPskPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeCertPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeCertX509CertPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeDeletePayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeEapPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeEncryptedPayloadBodyTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeHeaderTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeIdPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeKePayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeMessageTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeNoncePayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeNotifyPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeSaPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeSkPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeSkfPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeTestUtils.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/message/IkeTsPayloadTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/testutils/CertUtils.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/testutils/MockIpSecTestUtils.java delete mode 100644 tests/iketests/src/java/com/android/ike/ikev2/utils/RetransmitterTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/utils/BigIntegerUtilsTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/utils/LogTest.java delete mode 100644 tests/iketests/src/java/com/android/ike/utils/SimpleStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/TestUtils.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapAkaPrimeTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapAkaTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapAuthenticatorTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapErrorTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapMethodEndToEndTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapMsChapV2Test.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapResponseTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapSimTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapSuccessTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/EapTestUtils.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/crypto/Fips186_2PrfTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/crypto/HmacSha256ByteSignerTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/crypto/ParityBitUtilTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/EapDataTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/EapMessageTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/EapTestMessageDefinitions.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2ChallengeRequestTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2ChallengeResponseTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2FailureRequestTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2FailureResponseTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2PacketDefinitions.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2SuccessRequestTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2SuccessResponseTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/mschapv2/EapMsChapV2TypeDataTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeDataTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeDataTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaAttributeFactoryTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeDataTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtAutnTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtAutsTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtBiddingTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtClientErrorCodeTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtCounterTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtIdReqTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtIdentityTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtKdfInputTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtKdfTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtMacTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtNonceMtTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtNonceSTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtNotificationTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtPaddingTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtRandAkaTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtRandSimTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtResTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtSelectedVersionTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtVersionListTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/EapSimAkaAttributeTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/EapTestAttributeDefinitions.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/CreatedStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaChallengeStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaCreatedStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaIdentityStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaMethodStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaPrimeChallengeStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaPrimeCreatedStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaPrimeIdentityStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaPrimeMethodStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaPrimeStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaPrimeTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapAkaStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapMsChapV2AwaitingEapFailureStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapMsChapV2AwaitingEapSuccessStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapMsChapV2ChallengeStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapMsChapV2CreatedStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapMsChapV2MethodStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapMsChapV2StateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapMsChapV2ValidateAuthenticatorStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapSimAkaMethodStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapSimChallengeStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapSimCreatedStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapSimMethodStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapSimStartStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapSimStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/EapStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/IdentityStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/eap/statemachine/MethodStateTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/ChildSessionStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeLocalRequestSchedulerTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSocketTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/SaRecordTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeCombinedModeCipherTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacIntegrityTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacPrfTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/crypto/IkeNormalModeCipherTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeAuthDigitalSignPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeAuthPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeAuthPskPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeCertPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeCertX509CertPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeConfigPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeDeletePayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeEapPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeEncryptedPayloadBodyTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeHeaderTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeIdPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeKePayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeMessageTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeNoncePayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeNotifyPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeSaPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeSkPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeSkfPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeTestUtils.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/message/IkeTsPayloadTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/testutils/CertUtils.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/testutils/MockIpSecTestUtils.java create mode 100644 tests/iketests/src/java/com/android/internal/net/ipsec/ike/utils/RetransmitterTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/utils/BigIntegerUtilsTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/utils/LogTest.java create mode 100644 tests/iketests/src/java/com/android/internal/net/utils/SimpleStateMachineTest.java diff --git a/src/java/android/net/eap/EapSessionConfig.java b/src/java/android/net/eap/EapSessionConfig.java new file mode 100644 index 00000000..a31a0fdf --- /dev/null +++ b/src/java/android/net/eap/EapSessionConfig.java @@ -0,0 +1,234 @@ +/* + * 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 android.net.eap; + +import static com.android.internal.net.eap.message.EapData.EAP_TYPE_AKA; +import static com.android.internal.net.eap.message.EapData.EAP_TYPE_AKA_PRIME; +import static com.android.internal.net.eap.message.EapData.EAP_TYPE_MSCHAP_V2; +import static com.android.internal.net.eap.message.EapData.EAP_TYPE_SIM; + +import android.telephony.TelephonyManager.UiccAppType; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.eap.message.EapData.EapMethod; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * EapSessionConfig represents a container for EAP method configs to be used within an IKEv2 + * session. + * + *

The EAP authentication server decides which EAP method is used, so clients are encouraged to + * provide configs for several EAP methods. + */ +public final class EapSessionConfig { + @VisibleForTesting + static final byte[] DEFAULT_IDENTITY = new byte[0]; + + // IANA -> EapMethodConfig for that method + public final Map eapConfigs; + public final byte[] eapIdentity; + + @VisibleForTesting + public EapSessionConfig(Map eapConfigs, byte[] eapIdentity) { + this.eapConfigs = Collections.unmodifiableMap(eapConfigs); + this.eapIdentity = eapIdentity; + } + + /** This class can be used to incrementally construct an EapSessionConfig. */ + public static final class Builder { + private final Map mEapConfigs; + private byte[] mEapIdentity; + + /** + * Constructs and returns a new Builder for constructing an EapSessionConfig. + */ + public Builder() { + mEapConfigs = new HashMap<>(); + mEapIdentity = DEFAULT_IDENTITY; + } + + /** + * Sets the client's EAP Identity. + * + * @param eapIdentity byte[] representing the client's EAP Identity + * @return Builder this, to facilitate chaining. + */ + public Builder setEapIdentity(byte[] eapIdentity) { + this.mEapIdentity = eapIdentity.clone(); + return this; + } + + /** + * Sets the configuration for EAP SIM. + * + * @param subId int the client's subId to be authenticated + * @param apptype the {@link UiccAppType} apptype to be used for authentication + * @return Builder this, to facilitate chaining. + */ + public Builder setEapSimConfig(int subId, @UiccAppType int apptype) { + mEapConfigs.put(EAP_TYPE_SIM, new EapSimConfig(subId, apptype)); + return this; + } + + /** + * Sets the configuration for EAP AKA. + * + * @param subId int the client's subId to be authenticated + * @param apptype the {@link UiccAppType} apptype to be used for authentication + * @return Builder this, to facilitate chaining + */ + public Builder setEapAkaConfig(int subId, @UiccAppType int apptype) { + mEapConfigs.put(EAP_TYPE_AKA, new EapAkaConfig(subId, apptype)); + return this; + } + + /** + * Sets the configuration for EAP AKA'. + * + * @param subId int the client's subId to be authenticated + * @param apptype the {@link UiccAppType} apptype to be used for authentication + * @param networkName String the network name to be used for authentication. The String must + * be a UTF-8 String value + * @param allowMismatchedNetworkNames indicates whether the EAP library can ignore potential + * mismatches between the given network name and that received in an EAP-AKA' session. + * If false, mismatched network names will be handled as an Authentication Reject + * message. + * @return Builder this, to facilitate chaining + */ + public Builder setEapAkaPrimeConfig( + int subId, + @UiccAppType int apptype, + String networkName, + boolean allowMismatchedNetworkNames) { + mEapConfigs.put( + EAP_TYPE_AKA_PRIME, + new EapAkaPrimeConfig( + subId, apptype, networkName, allowMismatchedNetworkNames)); + return this; + } + + /** + * Sets the configuration for EAP MSCHAPv2. + * + * @param username String the client account's username to be authenticated + * @param password String the client account's password to be authenticated + * @return Builder this, to faciliate chaining + */ + public Builder setEapMsChapV2Config(String username, String password) { + mEapConfigs.put(EAP_TYPE_MSCHAP_V2, new EapMsChapV2Config(username, password)); + return this; + } + + /** + * Constructs and returns an EapSessionConfig with the configurations applied to this + * Builder. + * + * @return the EapSessionConfig constructed by this Builder + * @throws IllegalStateException iff no EAP methods have been configured + */ + public EapSessionConfig build() { + if (mEapConfigs.isEmpty()) { + throw new IllegalStateException("Must have at least one EAP method configured"); + } + + return new EapSessionConfig(mEapConfigs, mEapIdentity); + } + } + + /** EapMethodConfig represents a generic EAP method configuration. */ + public abstract static class EapMethodConfig { + @EapMethod public final int methodType; + + protected EapMethodConfig(@EapMethod int methodType) { + this.methodType = methodType; + } + } + + /** + * EapUiccConfig represents the configs needed for EAP methods that rely on UICC cards for + * authentication. + */ + public abstract static class EapUiccConfig extends EapMethodConfig { + public final int subId; + public final int apptype; + + private EapUiccConfig(@EapMethod int methodType, int subId, @UiccAppType int apptype) { + super(methodType); + this.subId = subId; + this.apptype = apptype; + } + } + + /** + * EapSimConfig represents the configs needed for an EAP SIM session. + */ + public static class EapSimConfig extends EapUiccConfig { + @VisibleForTesting + public EapSimConfig(int subId, @UiccAppType int apptype) { + super(EAP_TYPE_SIM, subId, apptype); + } + } + + /** + * EapAkaConfig represents the configs needed for an EAP AKA session. + */ + public static class EapAkaConfig extends EapUiccConfig { + @VisibleForTesting + public EapAkaConfig(int subId, @UiccAppType int apptype) { + super(EAP_TYPE_AKA, subId, apptype); + } + } + + /** + * EapAkaPrimeConfig represents the configs needed for an EAP-AKA' session. + */ + public static class EapAkaPrimeConfig extends EapAkaConfig { + public final String networkName; + public final boolean allowMismatchedNetworkNames; + + @VisibleForTesting + public EapAkaPrimeConfig( + int subId, + @UiccAppType int apptype, + String networkName, + boolean allowMismatchedNetworkNames) { + super(subId, apptype); + + this.networkName = networkName; + this.allowMismatchedNetworkNames = allowMismatchedNetworkNames; + } + } + + /** + * EapMsChapV2Config represents the configs needed for an EAP MSCHAPv2 session. + */ + public static class EapMsChapV2Config extends EapMethodConfig { + public final String username; + public final String password; + + @VisibleForTesting + public EapMsChapV2Config(String username, String password) { + super(EAP_TYPE_MSCHAP_V2); + + this.username = username; + this.password = password; + } + } +} diff --git a/src/java/android/net/ipsec/ike/ChildSaProposal.java b/src/java/android/net/ipsec/ike/ChildSaProposal.java new file mode 100644 index 00000000..c8851a71 --- /dev/null +++ b/src/java/android/net/ipsec/ike/ChildSaProposal.java @@ -0,0 +1,171 @@ +/* + * 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 android.net.ipsec.ike; + +import com.android.internal.net.ipsec.ike.message.IkePayload; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.DhGroupTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EncryptionTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EsnTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.IntegrityTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.Transform; + +import java.util.Arrays; +import java.util.List; + +/** + * ChildSaProposal represents a user configured set contains cryptograhic algorithms and key + * generating materials for negotiating an Child SA. + * + *

User must provide at least a valid ChildSaProposal when they are creating a new Child SA. + * + * @see RFC 7296, Internet Key Exchange + * Protocol Version 2 (IKEv2) + */ +public final class ChildSaProposal extends SaProposal { + private final EsnTransform[] mEsns; + + /** + * Construct an instance of ChildSaProposal. + * + *

This constructor is either called by ChildSaPayload for building an inbound proposal from + * a decoded packet, or called by the inner Builder to build an outbound proposal from user + * provided parameters + * + * @param encryptionAlgos encryption algorithms + * @param integrityAlgos integrity algorithms + * @param dhGroups Diffie-Hellman Groups + * @param esns ESN policies + */ + public ChildSaProposal( + EncryptionTransform[] encryptionAlgos, + IntegrityTransform[] integrityAlgos, + DhGroupTransform[] dhGroups, + EsnTransform[] esns) { + super(IkePayload.PROTOCOL_ID_ESP, encryptionAlgos, integrityAlgos, dhGroups); + mEsns = esns; + } + + /** Gets all ESN policies. */ + public EsnTransform[] getEsnTransforms() { + return mEsns; + } + + /** + * Gets a copy of proposal without all proposed DH groups. + * + *

This is used to avoid negotiating DH Group for negotiating first Child SA. + */ + public ChildSaProposal getCopyWithoutDhTransform() { + return new ChildSaProposal( + getEncryptionTransforms(), + getIntegrityTransforms(), + new DhGroupTransform[0], + getEsnTransforms()); + } + + @Override + public Transform[] getAllTransforms() { + List transformList = getAllTransformsAsList(); + transformList.addAll(Arrays.asList(mEsns)); + + return transformList.toArray(new Transform[transformList.size()]); + } + + @Override + public boolean isNegotiatedFrom(SaProposal reqProposal) { + return super.isNegotiatedFrom(reqProposal) + && isTransformSelectedFrom(mEsns, ((ChildSaProposal) reqProposal).mEsns); + } + + /** + * This class can be used to incrementally construct a ChildSaProposal. ChildSaProposal + * instances are immutable once built. + * + *

TODO: Support users to add algorithms from most preferred to least preferred. + */ + public static final class Builder extends SaProposal.Builder { + /** + * Adds an encryption algorithm with specific key length to SA proposal being built. + * + * @param algorithm encryption algorithm to add to ChildSaProposal. + * @param keyLength key length of algorithm. For algorithm that has fixed key length (e.g. + * 3DES) only KEY_LEN_UNUSED is allowed. + * @return Builder of ChildSaProposal. + * @throws IllegalArgumentException if AEAD and non-combined mode algorithms are mixed. + */ + public Builder addEncryptionAlgorithm(@EncryptionAlgorithm int algorithm, int keyLength) { + validateAndAddEncryptAlgo(algorithm, keyLength); + return this; + } + + /** + * Adds an integrity algorithm to SA proposal being built. + * + * @param algorithm integrity algorithm to add to ChildSaProposal. + * @return Builder of ChildSaProposal. + */ + public Builder addIntegrityAlgorithm(@IntegrityAlgorithm int algorithm) { + addIntegrityAlgo(algorithm); + return this; + } + + /** + * Adds a Diffie-Hellman Group to SA proposal being built. + * + * @param dhGroup to add to ChildSaProposal. + * @return Builder of ChildSaProposal. + */ + public Builder addDhGroup(@DhGroup int dhGroup) { + addDh(dhGroup); + return this; + } + + private IntegrityTransform[] buildIntegAlgosOrThrow() { + // When building Child SA Proposal with normal-mode ciphers, there is no contraint on + // integrity algorithm. When building Child SA Proposal with combined-mode ciphers, + // mProposedIntegrityAlgos must be either empty or only have INTEGRITY_ALGORITHM_NONE. + for (IntegrityTransform transform : mProposedIntegrityAlgos) { + if (transform.id != INTEGRITY_ALGORITHM_NONE && mHasAead) { + throw new IllegalArgumentException( + ERROR_TAG + + "Only INTEGRITY_ALGORITHM_NONE can be" + + " proposed with combined-mode ciphers in any proposal."); + } + } + + return mProposedIntegrityAlgos.toArray( + new IntegrityTransform[mProposedIntegrityAlgos.size()]); + } + + /** + * Validates, builds and returns the ChildSaProposal + * + * @return the validated ChildSaProposal. + * @throws IllegalArgumentException if ChildSaProposal is invalid. + */ + public ChildSaProposal build() { + EncryptionTransform[] encryptionTransforms = buildEncryptAlgosOrThrow(); + IntegrityTransform[] integrityTransforms = buildIntegAlgosOrThrow(); + + return new ChildSaProposal( + encryptionTransforms, + integrityTransforms, + mProposedDhGroups.toArray(new DhGroupTransform[mProposedDhGroups.size()]), + new EsnTransform[] {new EsnTransform()}); + } + } +} diff --git a/src/java/android/net/ipsec/ike/ChildSessionCallback.java b/src/java/android/net/ipsec/ike/ChildSessionCallback.java new file mode 100644 index 00000000..ec8722e6 --- /dev/null +++ b/src/java/android/net/ipsec/ike/ChildSessionCallback.java @@ -0,0 +1,66 @@ +/* + * 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 android.net.ipsec.ike; + +import android.net.IpSecManager.PolicyDirection; +import android.net.IpSecTransform; +import android.net.ipsec.ike.exceptions.IkeException; + +/** Callback interface for receiving state changes of a Child Session. */ +public interface ChildSessionCallback { + /** + * Called when Child Session setup succeeds. + * + * @param sessionConfiguration the configuration information of Child Session negotiated during + * Child creation. + */ + void onOpened(ChildSessionConfiguration sessionConfiguration); + + /** + * Called when either side has decided to close this Session and the deletion exchange + * finishes. + * + *

This method will not be fired if this deletion is caused by a fatal error. + */ + void onClosed(); + + /** + * Called if Child Session setup fails or Child Session is closed because of a fatal error. + * + * @param exception the detailed error. + */ + void onClosedExceptionally(IkeException exception); + + /** + * Called when a new {@link IpSecTransform} is created for this Child Session. + * + * @param ipSecTransform the created {@link IpSecTransform} + * @param direction the direction of this {@link IpSecTransform} + */ + void onIpSecTransformCreated(IpSecTransform ipSecTransform, @PolicyDirection int direction); + + /** + * Called when a new {@link IpSecTransform} is deleted for this Child Session. + * + *

Users MUST remove the transform from the socket or interface. Otherwise the communication + * on that socket or interface will fail. + * + * @param ipSecTransform the deleted {@link IpSecTransform} + * @param direction the direction of this {@link IpSecTransform} + */ + void onIpSecTransformDeleted(IpSecTransform ipSecTransform, @PolicyDirection int direction); +} diff --git a/src/java/android/net/ipsec/ike/ChildSessionConfiguration.java b/src/java/android/net/ipsec/ike/ChildSessionConfiguration.java new file mode 100644 index 00000000..2ed9de2f --- /dev/null +++ b/src/java/android/net/ipsec/ike/ChildSessionConfiguration.java @@ -0,0 +1,130 @@ +/* + * 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 android.net.ipsec.ike; + +import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; +import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; +import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_ADDRESS; + +import android.net.LinkAddress; + +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttribute; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Address; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Address; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** ChildSessionConfiguration represents the negotiated configuration for a Child Session. */ +public final class ChildSessionConfiguration { + private static final int IPv4_DEFAULT_PREFIX_LEN = 32; + + private final List mInboundTs; + private final List mOutboundTs; + private final List mInternalAddressList; + + /** + * Construct an instance of {@link ChildSessionConfiguration}. + * + *

It is only supported to build a {@link ChildSessionConfiguration} with a Configure(Reply) + * Payload. + */ + public ChildSessionConfiguration( + List inTs, + List outTs, + IkeConfigPayload configPayload) { + this(inTs, outTs); + + if (configPayload.configType != IkeConfigPayload.CONFIG_TYPE_REPLY) { + throw new IllegalArgumentException( + "Cannot build ChildSessionConfiguration with configuration type: " + + configPayload.configType); + } + + // It is validated in IkeConfigPayload that a config reply only has at most one non-empty + // netmask and netmask exists only when IPv4 internal address exists. + ConfigAttributeIpv4Netmask netmaskAttr = null; + for (ConfigAttribute att : configPayload.recognizedAttributeList) { + if (att.attributeType == CONFIG_ATTR_INTERNAL_IP4_NETMASK && !att.isEmptyValue()) { + netmaskAttr = (ConfigAttributeIpv4Netmask) att; + } + } + + for (ConfigAttribute att : configPayload.recognizedAttributeList) { + if (att.isEmptyValue()) continue; + switch (att.attributeType) { + case CONFIG_ATTR_INTERNAL_IP4_ADDRESS: + ConfigAttributeIpv4Address addressAttr = (ConfigAttributeIpv4Address) att; + if (netmaskAttr != null) { + mInternalAddressList.add( + new LinkAddress(addressAttr.address, netmaskAttr.getPrefixLen())); + } else { + mInternalAddressList.add( + new LinkAddress(addressAttr.address, IPv4_DEFAULT_PREFIX_LEN)); + } + break; + case CONFIG_ATTR_INTERNAL_IP4_NETMASK: + // No action. + break; + case CONFIG_ATTR_INTERNAL_IP6_ADDRESS: + mInternalAddressList.add(((ConfigAttributeIpv6Address) att).linkAddress); + break; + default: + // TODO: Support DNS,Subnet and Dhcp4 attributes + } + } + } + + /** Construct an instance of {@link ChildSessionConfiguration}. */ + public ChildSessionConfiguration( + List inTs, List outTs) { + mInboundTs = Collections.unmodifiableList(inTs); + mOutboundTs = Collections.unmodifiableList(outTs); + mInternalAddressList = new LinkedList<>(); + } + + /** + * Returns the negotiated inbound traffic selectors. + * + * @return the inbound traffic selector. + */ + public List getInboundTrafficSelectors() { + return mInboundTs; + } + + /** + * Returns the negotiated outbound traffic selectors. + * + * @return the outbound traffic selector. + */ + public List getOutboundTrafficSelectors() { + return mOutboundTs; + } + + /** + * Returns the assigned internal addresses. + * + * @return assigned internal addresses, or empty list when no addresses are assigned by the + * remote IKE server. + */ + public List getInternalAddressList() { + return mInternalAddressList; + } +} diff --git a/src/java/android/net/ipsec/ike/ChildSessionOptions.java b/src/java/android/net/ipsec/ike/ChildSessionOptions.java new file mode 100644 index 00000000..90a30053 --- /dev/null +++ b/src/java/android/net/ipsec/ike/ChildSessionOptions.java @@ -0,0 +1,119 @@ +/* + * 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 android.net.ipsec.ike; + +import libcore.net.InetAddressUtils; + +import java.net.InetAddress; +import java.util.LinkedList; +import java.util.List; + +/** + * This abstract class is the superclass of all classes representing a set of user configurations + * for Child Session negotiation. + */ +public abstract class ChildSessionOptions { + private static final IkeTrafficSelector DEFAULT_TRAFFIC_SELECTOR_IPV4; + // TODO: b/130765172 Add TRAFFIC_SELECTOR_IPV6 and instantiate it. + + static { + DEFAULT_TRAFFIC_SELECTOR_IPV4 = + buildDefaultTrafficSelector( + IkeTrafficSelector.TRAFFIC_SELECTOR_TYPE_IPV4_ADDR_RANGE); + } + + private final IkeTrafficSelector[] mLocalTrafficSelectors; + private final IkeTrafficSelector[] mRemoteTrafficSelectors; + private final ChildSaProposal[] mSaProposals; + private final boolean mIsTransport; + + protected ChildSessionOptions( + IkeTrafficSelector[] localTs, + IkeTrafficSelector[] remoteTs, + ChildSaProposal[] proposals, + boolean isTransport) { + mLocalTrafficSelectors = localTs; + mRemoteTrafficSelectors = remoteTs; + mSaProposals = proposals; + mIsTransport = isTransport; + } + + public IkeTrafficSelector[] getLocalTrafficSelectors() { + return mLocalTrafficSelectors; + } + + public IkeTrafficSelector[] getRemoteTrafficSelectors() { + return mRemoteTrafficSelectors; + } + + public ChildSaProposal[] getSaProposals() { + return mSaProposals; + } + + public boolean isTransportMode() { + return mIsTransport; + } + + /** This class represents common information for Child Sesison Options Builders. */ + protected abstract static class Builder { + protected final List mLocalTsList = new LinkedList<>(); + protected final List mRemoteTsList = new LinkedList<>(); + protected final List mSaProposalList = new LinkedList<>(); + + protected Builder() { + // Currently IKE library only accepts setting up Child SA that all ports and all + // addresses are allowed on both sides. The protected traffic range is determined by the + // socket or interface that the {@link IpSecTransform} is applied to. + // TODO: b/130756765 Validate the current TS negotiation strategy. + mLocalTsList.add(DEFAULT_TRAFFIC_SELECTOR_IPV4); + mRemoteTsList.add(DEFAULT_TRAFFIC_SELECTOR_IPV4); + // TODO: add IPv6 TS to ChildSessionOptions. + } + + protected void validateAndAddSaProposal(ChildSaProposal proposal) { + mSaProposalList.add(proposal); + } + + protected void validateOrThrow() { + if (mSaProposalList.isEmpty()) { + throw new IllegalArgumentException( + "ChildSessionOptions requires at least one Child SA proposal."); + } + } + } + + private static IkeTrafficSelector buildDefaultTrafficSelector( + @IkeTrafficSelector.TrafficSelectorType int tsType) { + int startPort = IkeTrafficSelector.PORT_NUMBER_MIN; + int endPort = IkeTrafficSelector.PORT_NUMBER_MAX; + InetAddress startAddress = null; + InetAddress endAddress = null; + switch (tsType) { + case IkeTrafficSelector.TRAFFIC_SELECTOR_TYPE_IPV4_ADDR_RANGE: + startAddress = InetAddressUtils.parseNumericAddress("0.0.0.0"); + endAddress = InetAddressUtils.parseNumericAddress("255.255.255.255"); + break; + case IkeTrafficSelector.TRAFFIC_SELECTOR_TYPE_IPV6_ADDR_RANGE: + // TODO: Support it. + throw new UnsupportedOperationException("Do not support IPv6."); + default: + throw new IllegalArgumentException("Invalid Traffic Selector type: " + tsType); + } + + return new IkeTrafficSelector(tsType, startPort, endPort, startAddress, endAddress); + } +} diff --git a/src/java/android/net/ipsec/ike/IkeFqdnIdentification.java b/src/java/android/net/ipsec/ike/IkeFqdnIdentification.java new file mode 100644 index 00000000..393a0723 --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeFqdnIdentification.java @@ -0,0 +1,76 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.NonNull; + +import java.nio.charset.Charset; +import java.util.Objects; + +/** IkeFqdnIdentification represents ID information using a fully-qualified domain name (FQDN) */ +public class IkeFqdnIdentification extends IkeIdentification { + private static final Charset ASCII = Charset.forName("US-ASCII"); + + public final String fqdn; + + /** + * Construct an instance of IkeFqdnIdentification from a decoded inbound packet. + * + *

All characters in the FQDN are ASCII. + * + * @param fqdnBytes FQDN in byte array. + */ + public IkeFqdnIdentification(byte[] fqdnBytes) { + super(ID_TYPE_FQDN); + fqdn = new String(fqdnBytes, ASCII); + } + + /** + * Construct an instance of IkeFqdnIdentification with user provided fully-qualified domain name + * (FQDN) for building outbound packet. + * + *

FQDN will be formatted as US-ASCII. + * + * @param fqdn user provided fully-qualified domain name (FQDN) + */ + public IkeFqdnIdentification(@NonNull String fqdn) { + super(ID_TYPE_FQDN); + this.fqdn = fqdn; + } + + @Override + public int hashCode() { + return Objects.hash(idType, fqdn); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IkeFqdnIdentification)) return false; + + return fqdn.equals(((IkeFqdnIdentification) o).fqdn); + } + + /** + * Retrieve the byte-representation of the FQDN. + * + * @return the byte-representation of the FQDN. + */ + @Override + public byte[] getEncodedIdData() { + return fqdn.getBytes(ASCII); + } +} diff --git a/src/java/android/net/ipsec/ike/IkeIdentification.java b/src/java/android/net/ipsec/ike/IkeIdentification.java new file mode 100644 index 00000000..737df826 --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeIdentification.java @@ -0,0 +1,80 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.IntDef; +import android.util.ArraySet; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Set; + +/** + * IkeIdentification is abstract base class that represents the common information for all types of + * IKE entity identification. + * + * @see RFC 7296, Internet Key Exchange + * Protocol Version 2 (IKEv2) + */ +public abstract class IkeIdentification { + // Set of supported ID types. + private static final Set SUPPORTED_ID_TYPES; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + ID_TYPE_IPV4_ADDR, + ID_TYPE_FQDN, + ID_TYPE_RFC822_ADDR, + ID_TYPE_IPV6_ADDR, + ID_TYPE_DER_ASN1_DN, + ID_TYPE_DER_ASN1_GN, + ID_TYPE_KEY_ID + }) + public @interface IdType {} + + public static final int ID_TYPE_IPV4_ADDR = 1; + public static final int ID_TYPE_FQDN = 2; + public static final int ID_TYPE_RFC822_ADDR = 3; + public static final int ID_TYPE_IPV6_ADDR = 5; + public static final int ID_TYPE_DER_ASN1_DN = 9; + public static final int ID_TYPE_DER_ASN1_GN = 10; + public static final int ID_TYPE_KEY_ID = 11; + + static { + SUPPORTED_ID_TYPES = new ArraySet(); + SUPPORTED_ID_TYPES.add(ID_TYPE_IPV4_ADDR); + SUPPORTED_ID_TYPES.add(ID_TYPE_FQDN); + SUPPORTED_ID_TYPES.add(ID_TYPE_RFC822_ADDR); + SUPPORTED_ID_TYPES.add(ID_TYPE_IPV6_ADDR); + SUPPORTED_ID_TYPES.add(ID_TYPE_DER_ASN1_DN); + SUPPORTED_ID_TYPES.add(ID_TYPE_DER_ASN1_GN); + SUPPORTED_ID_TYPES.add(ID_TYPE_KEY_ID); + } + + public final int idType; + + protected IkeIdentification(@IdType int type) { + idType = type; + } + + /** + * Return the encoded identification data in a byte array. + * + * @return the encoded identification data. + */ + public abstract byte[] getEncodedIdData(); +} diff --git a/src/java/android/net/ipsec/ike/IkeIpv4AddrIdentification.java b/src/java/android/net/ipsec/ike/IkeIpv4AddrIdentification.java new file mode 100644 index 00000000..350187ed --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeIpv4AddrIdentification.java @@ -0,0 +1,78 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.NonNull; + +import com.android.internal.net.ipsec.ike.exceptions.AuthenticationFailedException; + +import java.net.Inet4Address; +import java.net.UnknownHostException; +import java.util.Objects; + +/** IkeIpv4AddrIdentification represents ID information in IPv4 address ID type. */ +public final class IkeIpv4AddrIdentification extends IkeIdentification { + public final Inet4Address ipv4Address; + + /** + * Construct an instance of IkeIpv4AddrIdentification from a decoded inbound packet. + * + * @param ipv4AddrBytes IPv4 address in byte array. + * @throws AuthenticationFailedException for decoding bytes error. + */ + public IkeIpv4AddrIdentification(byte[] ipv4AddrBytes) throws AuthenticationFailedException { + super(ID_TYPE_IPV4_ADDR); + try { + ipv4Address = (Inet4Address) (Inet4Address.getByAddress(ipv4AddrBytes)); + } catch (ClassCastException | UnknownHostException e) { + throw new AuthenticationFailedException(e); + } + } + + /** + * Construct an instance of IkeIpv4AddrIdentification with user provided IPv4 address for + * building outbound packet. + * + * @param address user provided IPv4 address + */ + public IkeIpv4AddrIdentification(@NonNull Inet4Address address) { + super(ID_TYPE_IPV4_ADDR); + ipv4Address = address; + } + + @Override + public int hashCode() { + return Objects.hash(idType, ipv4Address); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IkeIpv4AddrIdentification)) return false; + + return ipv4Address.equals(((IkeIpv4AddrIdentification) o).ipv4Address); + } + + /** + * Retrieve the byte-representation of the IPv4 address. + * + * @return the byte-representation of the IPv4 address. + */ + @Override + public byte[] getEncodedIdData() { + return ipv4Address.getAddress(); + } +} diff --git a/src/java/android/net/ipsec/ike/IkeIpv6AddrIdentification.java b/src/java/android/net/ipsec/ike/IkeIpv6AddrIdentification.java new file mode 100644 index 00000000..dfc7d5e3 --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeIpv6AddrIdentification.java @@ -0,0 +1,78 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.NonNull; + +import com.android.internal.net.ipsec.ike.exceptions.AuthenticationFailedException; + +import java.net.Inet6Address; +import java.net.UnknownHostException; +import java.util.Objects; + +/** IkeIpv6AddrIdentification represents ID information in IPv6 address ID type. */ +public class IkeIpv6AddrIdentification extends IkeIdentification { + public final Inet6Address ipv6Address; + + /** + * Construct an instance of IkeIpv6AddrIdentification from a decoded inbound packet. + * + * @param ipv6AddrBytes IPv6 address in byte array. + * @throws AuthenticationFailedException for decoding bytes error. + */ + public IkeIpv6AddrIdentification(byte[] ipv6AddrBytes) throws AuthenticationFailedException { + super(ID_TYPE_IPV6_ADDR); + try { + ipv6Address = (Inet6Address) (Inet6Address.getByAddress(ipv6AddrBytes)); + } catch (ClassCastException | UnknownHostException e) { + throw new AuthenticationFailedException(e); + } + } + + /** + * Construct an instance of IkeIpv6AddrIdentification with user provided IPv6 address for + * building outbound packet. + * + * @param address user provided IPv6 address + */ + public IkeIpv6AddrIdentification(@NonNull Inet6Address address) { + super(ID_TYPE_IPV6_ADDR); + ipv6Address = address; + } + + @Override + public int hashCode() { + return Objects.hash(idType, ipv6Address); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IkeIpv6AddrIdentification)) return false; + + return ipv6Address.equals(((IkeIpv6AddrIdentification) o).ipv6Address); + } + + /** + * Retrieve the byte-representation of the IPv6 address. + * + * @return the byte-representation of the IPv6 address. + */ + @Override + public byte[] getEncodedIdData() { + return ipv6Address.getAddress(); + } +} diff --git a/src/java/android/net/ipsec/ike/IkeKeyIdIdentification.java b/src/java/android/net/ipsec/ike/IkeKeyIdIdentification.java new file mode 100644 index 00000000..c229b9da --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeKeyIdIdentification.java @@ -0,0 +1,63 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.NonNull; + +import java.util.Objects; + +/** + * This class represents IKE ID information in Key ID type. + * + *

This is an octet stream that may be used to pass vendor-specific information necessary to do + * certain proprietary types of identification. + */ +public final class IkeKeyIdIdentification extends IkeIdentification { + public final byte[] keyId; + + /** + * Construct an instance of IkeKeyIdIdentification with provided Key ID + * + * @param keyId Key ID in bytes + */ + public IkeKeyIdIdentification(@NonNull byte[] keyId) { + super(ID_TYPE_KEY_ID); + this.keyId = keyId; + } + + @Override + public int hashCode() { + return Objects.hash(idType, keyId); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IkeKeyIdIdentification)) return false; + + return keyId.equals(((IkeKeyIdIdentification) o).keyId); + } + + /** + * Retrieve the byte-representation of the FQDN. + * + * @return the byte-representation of the FQDN. + */ + @Override + public byte[] getEncodedIdData() { + return keyId; + } +} diff --git a/src/java/android/net/ipsec/ike/IkeManager.java b/src/java/android/net/ipsec/ike/IkeManager.java new file mode 100644 index 00000000..ef8b893b --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeManager.java @@ -0,0 +1,94 @@ +/* + * 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 android.net.ipsec.ike; + +import android.content.Context; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.utils.Log; + +import java.util.concurrent.Executor; + +/** This class contains methods for managing IKE sessions. */ +public final class IkeManager { + private static final String IKE_TAG = "IKE"; + private static final boolean LOG_SENSITIVE = false; + + private static Log sIkeLog = new Log(IKE_TAG, LOG_SENSITIVE); + + private final Context mContext; + + /** + * Construct an instance of {@link IkeManager} + * + * @param context the application context. + */ + public IkeManager(Context context) { + mContext = context; + } + + /** + * Construct an instance of {@link IkeSession} and start the IKE Session setup process. + * + *

This method will immediately return a management object {@link IkeSession} and + * asynchronously initiate the IKE Session setup process. Users will be notified of the IKE + * Session and Child Session negotiation results on the callback arguments. + * + * @param ikeSessionOptions the {@link IkeSessionOptions} that contains acceptable IKE Session + * configurations. + * @param firstChildSessionOptions the {@link ChildSessionOptions} that contains acceptable + * first Child Session configurations. + * @param userCbExecutor the {@link Executor} upon which all callbacks will be posted. For + * security and consistency, the callbacks posted to this executor MUST be executed + * serially, in the order they were posted. + * @param ikeSessionCallback the {@link IkeSessionCallback} interface to notify users the state + * changes of the IKE Session. + * @param firstChildSessionCallback the {@link ChildSessionCallback} interface to notify users + * the state changes of the Child Session. + * @return an instance of {@link IkeSession} + */ + public IkeSession openIkeSession( + IkeSessionOptions ikeSessionOptions, + ChildSessionOptions firstChildSessionOptions, + Executor userCbExecutor, + IkeSessionCallback ikeSessionCallback, + ChildSessionCallback firstChildSessionCallback) { + return new IkeSession( + mContext, + ikeSessionOptions, + firstChildSessionOptions, + userCbExecutor, + ikeSessionCallback, + firstChildSessionCallback); + } + + /** Returns IKE logger. */ + public static Log getIkeLog() { + return sIkeLog; + } + + /** Injects IKE logger for testing. */ + @VisibleForTesting + public static void setIkeLog(Log log) { + sIkeLog = log; + } + + /** Resets IKE logger. */ + @VisibleForTesting + public static void resetIkeLog() { + sIkeLog = new Log(IKE_TAG, LOG_SENSITIVE); + } +} diff --git a/src/java/android/net/ipsec/ike/IkeRfc822AddrIdentification.java b/src/java/android/net/ipsec/ike/IkeRfc822AddrIdentification.java new file mode 100644 index 00000000..2a93bea1 --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeRfc822AddrIdentification.java @@ -0,0 +1,76 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.NonNull; + +import java.nio.charset.Charset; +import java.util.Objects; + +/** This class represents IKE ID information in fully-qualified RFC 822 email address ID type. */ +public final class IkeRfc822AddrIdentification extends IkeIdentification { + private static final Charset UTF8 = Charset.forName("UTF-8"); + + public final String rfc822Name; + + /** + * Construct an instance of IkeRfc822AddrIdentification from a decoded inbound packet. + * + *

All characters in the RFC 822 email address are UTF-8. + * + * @param rfc822NameBytes fully-qualified RFC 822 email address in byte array. + */ + public IkeRfc822AddrIdentification(byte[] rfc822NameBytes) { + super(ID_TYPE_RFC822_ADDR); + rfc822Name = new String(rfc822NameBytes, UTF8); + } + + /** + * Construct an instance of IkeRfc822AddrIdentification with user provided fully-qualified RFC + * 822 email address for building outbound packet. + * + *

rfc822Name will be formatted as UTF-8. + * + * @param rfc822Name user provided fully-qualified RFC 822 email address. + */ + public IkeRfc822AddrIdentification(@NonNull String rfc822Name) { + super(ID_TYPE_RFC822_ADDR); + this.rfc822Name = rfc822Name; + } + + @Override + public int hashCode() { + return Objects.hash(idType, rfc822Name); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IkeRfc822AddrIdentification)) return false; + + return rfc822Name.equals(((IkeRfc822AddrIdentification) o).rfc822Name); + } + + /** + * Retrieve the byte-representation of the the RFC 822 email address. + * + * @return the byte-representation of the RFC 822 email address. + */ + @Override + public byte[] getEncodedIdData() { + return rfc822Name.getBytes(UTF8); + } +} diff --git a/src/java/android/net/ipsec/ike/IkeSaProposal.java b/src/java/android/net/ipsec/ike/IkeSaProposal.java new file mode 100644 index 00000000..1494f9d4 --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeSaProposal.java @@ -0,0 +1,209 @@ +/* + * 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 android.net.ipsec.ike; + +import android.util.ArraySet; + +import com.android.internal.net.ipsec.ike.message.IkePayload; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.DhGroupTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EncryptionTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.IntegrityTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.PrfTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.Transform; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** + * IkeSaProposal represents a user configured set contains cryptograhic algorithms and key + * generating materials for negotiating an IKE SA. + * + *

User must provide at least a valid IkeSaProposal when they are creating a new IKE SA. + * + * @see RFC 7296, Internet Key Exchange + * Protocol Version 2 (IKEv2) + */ +public final class IkeSaProposal extends SaProposal { + private final PrfTransform[] mPseudorandomFunctions; + + /** + * Construct an instance of IkeSaProposal. + * + *

This constructor is either called by IkeSaPayload for building an inbound proposal from a + * decoded packet, or called by the inner Builder to build an outbound proposal from user + * provided parameters + * + * @param encryptionAlgos encryption algorithms + * @param prfs pseudorandom functions + * @param integrityAlgos integrity algorithms + * @param dhGroups Diffie-Hellman Groups + */ + public IkeSaProposal( + EncryptionTransform[] encryptionAlgos, + PrfTransform[] prfs, + IntegrityTransform[] integrityAlgos, + DhGroupTransform[] dhGroups) { + super(IkePayload.PROTOCOL_ID_IKE, encryptionAlgos, integrityAlgos, dhGroups); + mPseudorandomFunctions = prfs; + } + + /** Gets all PRFs. */ + public PrfTransform[] getPrfTransforms() { + return mPseudorandomFunctions; + } + + @Override + public Transform[] getAllTransforms() { + List transformList = getAllTransformsAsList(); + transformList.addAll(Arrays.asList(mPseudorandomFunctions)); + + return transformList.toArray(new Transform[transformList.size()]); + } + + @Override + public boolean isNegotiatedFrom(SaProposal reqProposal) { + return super.isNegotiatedFrom(reqProposal) + && isTransformSelectedFrom( + mPseudorandomFunctions, + ((IkeSaProposal) reqProposal).mPseudorandomFunctions); + } + + /** + * This class can be used to incrementally construct a IkeSaProposal. IkeSaProposal instances + * are immutable once built. + * + *

TODO: Support users to add algorithms from most preferred to least preferred. + */ + public static final class Builder extends SaProposal.Builder { + // Use set to avoid adding repeated algorithms. + private final Set mProposedPrfs = new ArraySet<>(); + + /** + * Adds an encryption algorithm with specific key length to SA proposal being built. + * + * @param algorithm encryption algorithm to add to IkeSaProposal. + * @param keyLength key length of algorithm. For algorithm that has fixed key length (e.g. + * 3DES) only KEY_LEN_UNUSED is allowed. + * @return Builder of IkeSaProposal. + * @throws IllegalArgumentException if AEAD and non-combined mode algorithms are mixed. + */ + public Builder addEncryptionAlgorithm(@EncryptionAlgorithm int algorithm, int keyLength) { + validateAndAddEncryptAlgo(algorithm, keyLength); + return this; + } + + /** + * Adds an integrity algorithm to SA proposal being built. + * + * @param algorithm integrity algorithm to add to IkeSaProposal. + * @return Builder of IkeSaProposal. + */ + public Builder addIntegrityAlgorithm(@IntegrityAlgorithm int algorithm) { + addIntegrityAlgo(algorithm); + return this; + } + + /** + * Adds a Diffie-Hellman Group to SA proposal being built. + * + * @param dhGroup to add to IkeSaProposal. + * @return Builder of IkeSaProposal. + */ + public Builder addDhGroup(@DhGroup int dhGroup) { + addDh(dhGroup); + return this; + } + + /** + * Adds a pseudorandom function to SA proposal being built. + * + * @param algorithm pseudorandom function to add to IkeSaProposal. + * @return Builder of IkeSaProposal. + */ + public Builder addPseudorandomFunction(@PseudorandomFunction int algorithm) { + // Construct PrfTransform and validate proposed algorithm during construction. + mProposedPrfs.add(new PrfTransform(algorithm)); + return this; + } + + private IntegrityTransform[] buildIntegAlgosOrThrow() { + // When building IKE SA Proposal with normal-mode ciphers, mProposedIntegrityAlgos must + // not be empty and must not have INTEGRITY_ALGORITHM_NONE. When building IKE SA + // Proposal with combined-mode ciphers, mProposedIntegrityAlgos must be either empty or + // only have INTEGRITY_ALGORITHM_NONE. + if (mProposedIntegrityAlgos.isEmpty() && !mHasAead) { + throw new IllegalArgumentException( + ERROR_TAG + + "Integrity algorithm " + + "must be proposed with normal ciphers in IKE proposal."); + } + + for (IntegrityTransform transform : mProposedIntegrityAlgos) { + if ((transform.id == INTEGRITY_ALGORITHM_NONE) != mHasAead) { + throw new IllegalArgumentException( + ERROR_TAG + + "Invalid integrity algorithm configuration" + + " for this SA Proposal"); + } + } + + return mProposedIntegrityAlgos.toArray( + new IntegrityTransform[mProposedIntegrityAlgos.size()]); + } + + private DhGroupTransform[] buildDhGroupsOrThrow() { + if (mProposedDhGroups.isEmpty()) { + throw new IllegalArgumentException( + ERROR_TAG + "DH group must be proposed in IKE SA proposal."); + } + + for (DhGroupTransform transform : mProposedDhGroups) { + if (transform.id == DH_GROUP_NONE) { + throw new IllegalArgumentException( + ERROR_TAG + "None-value DH group invalid in IKE SA proposal"); + } + } + + return mProposedDhGroups.toArray(new DhGroupTransform[mProposedDhGroups.size()]); + } + + private PrfTransform[] buildPrfsOrThrow() { + if (mProposedPrfs.isEmpty()) { + throw new IllegalArgumentException( + ERROR_TAG + "PRF must be proposed in IKE SA proposal."); + } + return mProposedPrfs.toArray(new PrfTransform[mProposedPrfs.size()]); + } + + /** + * Validates, builds and returns the IkeSaProposal + * + * @return the validated IkeSaProposal. + * @throws IllegalArgumentException if IkeSaProposal is invalid. + */ + public IkeSaProposal build() { + EncryptionTransform[] encryptionTransforms = buildEncryptAlgosOrThrow(); + PrfTransform[] prfTransforms = buildPrfsOrThrow(); + IntegrityTransform[] integrityTransforms = buildIntegAlgosOrThrow(); + DhGroupTransform[] dhGroupTransforms = buildDhGroupsOrThrow(); + + return new IkeSaProposal( + encryptionTransforms, prfTransforms, integrityTransforms, dhGroupTransforms); + } + } +} diff --git a/src/java/android/net/ipsec/ike/IkeSession.java b/src/java/android/net/ipsec/ike/IkeSession.java new file mode 100644 index 00000000..97fe061e --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeSession.java @@ -0,0 +1,190 @@ +/* + * 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 android.net.ipsec.ike; + +import android.content.Context; +import android.net.IpSecManager; +import android.os.HandlerThread; +import android.os.Looper; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.ipsec.ike.IkeSessionStateMachine; + +import dalvik.system.CloseGuard; + +import java.util.concurrent.Executor; + +/** + * This class represents an IKE Session management object that allows for keying and management of + * {@link IpSecTransform}s. + * + *

An IKE/Child Session represents an IKE/Child SA as well as its rekeyed successors. A Child + * Session is bounded by the lifecycle of the IKE Session under which it is set up. Closing an IKE + * Session implicitly closes any remaining Child Sessions under it. + * + *

An IKE procedure is one or multiple IKE message exchanges that are used to create, delete or + * rekey an IKE Session or Child Session. + * + *

This class provides methods for user to initiate IKE procedures, such as the Creation and + * Deletion of a Child Session, or the Deletion of the IKE session. All procedures (except for IKE + * deletion) will be initiated sequentially after IKE Session is set up. + * + * @see RFC 7296, Internet Key Exchange Protocol + * Version 2 (IKEv2) + */ +public final class IkeSession implements AutoCloseable { + private final CloseGuard mCloseGuard = CloseGuard.get(); + + @VisibleForTesting final IkeSessionStateMachine mIkeSessionStateMachine; + + /** Package private */ + IkeSession( + Context context, + IkeSessionOptions ikeSessionOptions, + ChildSessionOptions firstChildSessionOptions, + Executor userCbExecutor, + IkeSessionCallback ikeSessionCallback, + ChildSessionCallback firstChildSessionCallback) { + this( + IkeThreadHolder.IKE_WORKER_THREAD.getLooper(), + context, + (IpSecManager) context.getSystemService(Context.IPSEC_SERVICE), + ikeSessionOptions, + firstChildSessionOptions, + userCbExecutor, + ikeSessionCallback, + firstChildSessionCallback); + } + + /** Package private */ + @VisibleForTesting + IkeSession( + Looper looper, + Context context, + IpSecManager ipSecManager, + IkeSessionOptions ikeSessionOptions, + ChildSessionOptions firstChildSessionOptions, + Executor userCbExecutor, + IkeSessionCallback ikeSessionCallback, + ChildSessionCallback firstChildSessionCallback) { + mIkeSessionStateMachine = + new IkeSessionStateMachine( + looper, + context, + ipSecManager, + ikeSessionOptions, + firstChildSessionOptions, + userCbExecutor, + ikeSessionCallback, + firstChildSessionCallback); + mIkeSessionStateMachine.openSession(); + + mCloseGuard.open("open"); + } + + @Override + public void finalize() { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + } + + /** Initialization-on-demand holder */ + private static class IkeThreadHolder { + static final HandlerThread IKE_WORKER_THREAD; + + static { + IKE_WORKER_THREAD = new HandlerThread("IkeWorkerThread"); + IKE_WORKER_THREAD.start(); + } + } + + // TODO: b/133340675 Destroy the worker thread when there is no more alive {@link IkeSession}. + + /** + * Asynchronously request a new Child Session. + * + *

Users MUST provide a unique {@link ChildSessionCallback} instance for each new Child + * Session. + * + *

Upon setup, the {@link ChildSessionCallback#onOpened(ChildSessionConfiguration)} will be + * fired. + * + * @param childSessionOptions the {@link ChildSessionOptions} that contains the Child Session + * configurations to negotiate. + * @param childSessionCallback the {@link ChildSessionCallback} interface to notify users the + * state changes of the Child Session. + * @throws IllegalArgumentException if the ChildSessionCallback is already in use. + */ + public void openChildSession( + ChildSessionOptions childSessionOptions, ChildSessionCallback childSessionCallback) { + mIkeSessionStateMachine.openChildSession(childSessionOptions, childSessionCallback); + } + + /** + * Asynchronously delete a Child Session. + * + *

Upon closing, the {@link ChildSessionCallback#onClosed()} will be fired. + * + * @param childSessionCallback The {@link ChildSessionCallback} instance that uniquely identify + * the Child Session. + * @throws IllegalArgumentException if no Child Session found bound with this callback. + */ + public void closeChildSession(ChildSessionCallback childSessionCallback) { + mIkeSessionStateMachine.closeChildSession(childSessionCallback); + } + + /** + * Close the IKE session gracefully. + * + *

Implements {@link AutoCloseable#close()} + * + *

Upon closing, the {@link IkeSessionCallback#onClosed()} will be fired. + * + *

Closing an IKE Session implicitly closes any remaining Child Sessions negotiated under it. + * Users SHOULD stop all outbound traffic that uses these Child Sessions({@link IpSecTransform} + * pairs) before calling this method. Otherwise IPsec packets will be dropped due to the lack of + * a valid {@link IpSecTransform}. + * + *

Closure of an IKE session will take priority over, and cancel other procedures waiting in + * the queue (but will wait for ongoing locally initiated procedures to complete). After sending + * the Delete request, the IKE library will wait until a Delete response is received or + * retransmission timeout occurs. + */ + @Override + public void close() throws Exception { + mCloseGuard.close(); + mIkeSessionStateMachine.closeSession(); + } + + /** + * Terminate (forcibly close) the IKE session. + * + *

Upon closing, the {@link IkeSessionCallback#onClosed()} will be fired. + * + *

Closing an IKE Session implicitly closes any remaining Child Sessions negotiated under it. + * Users SHOULD stop all outbound traffic that uses these Child Sessions({@link IpSecTransform} + * pairs) before calling this method. Otherwise IPsec packets will be dropped due to the lack of + * a valid {@link IpSecTransform}. + * + *

Forcible closure of an IKE session will take priority over, and cancel other procedures + * waiting in the queue. It will also interrupt any ongoing locally initiated procedure. + */ + public void kill() throws Exception { + mCloseGuard.close(); + mIkeSessionStateMachine.killSession(); + } +} diff --git a/src/java/android/net/ipsec/ike/IkeSessionCallback.java b/src/java/android/net/ipsec/ike/IkeSessionCallback.java new file mode 100644 index 00000000..c2121e2d --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeSessionCallback.java @@ -0,0 +1,57 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.NonNull; +import android.net.ipsec.ike.exceptions.IkeException; + +/** Callback interface for receiving state changes of an IKE Session. */ +public interface IkeSessionCallback { + /** + * Called when negotiation and authentication for this new IKE Session succeeds. + * + * @param sessionConfiguration the configuration information of IKE Session negotiated during + * IKE setup. + */ + void onOpened(@NonNull IkeSessionConfiguration sessionConfiguration); + + /** + * Called when either side has decided to close this Session and the deletion exchange + * finishes. + * + *

This method will not be fired if this deletion is caused by a fatal error. + */ + void onClosed(); + + /** + * Called if IKE Session negotiation fails or IKE Session is closed because of a fatal error. + * + * @param exception the detailed error. + */ + void onClosedExceptionally(IkeException exception); + + /** + * Called if a recoverable error is encountered in an established IKE Session. + * + *

A potential risk is usually detected when IKE library receives a non-protected error + * notification (e.g. INVALID_IKE_SPI) or a non-fatal error notification (e.g. + * INVALID_MESSAGE_ID). + * + * @param exception the detailed error. + */ + void onError(IkeException exception); +} diff --git a/src/java/android/net/ipsec/ike/IkeSessionConfiguration.java b/src/java/android/net/ipsec/ike/IkeSessionConfiguration.java new file mode 100644 index 00000000..6bbef7d0 --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeSessionConfiguration.java @@ -0,0 +1,59 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.IntDef; +import android.annotation.NonNull; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** IkeSessionConfiguration represents the negotiated configuration for a IKE Session. */ +public final class IkeSessionConfiguration { + @Retention(RetentionPolicy.SOURCE) + @IntDef({EXTENSION_TYPE_FRAGMENTATION, EXTENSION_TYPE_MOBIKE}) + public @interface ExtensionType {} + + public static final int EXTENSION_TYPE_FRAGMENTATION = 1; + public static final int EXTENSION_TYPE_MOBIKE = 2; + + /** + * Gets remote(server) version information. + * + * @return application version of the remote server, or empty string if the remote server did + * not provide the application version + */ + @NonNull + public String getRemoteApplicationVersion() { + return ""; + } + + /** + * Checks if an IKE extension is enabled. + * + *

An IKE extension is enabled when both sides can support it. This negotiation always + * happens in IKE initial changes(IKE INIT and IKE AUTH). + * + * @param extensionType the extension type + * @return {@code true} if this extension is enabled + */ + public boolean isIkeExtensionEnabled(@ExtensionType int extensionType) { + return false; + } + + // TODO: Implement IkeSessionConfiguration. +} diff --git a/src/java/android/net/ipsec/ike/IkeSessionOptions.java b/src/java/android/net/ipsec/ike/IkeSessionOptions.java new file mode 100644 index 00000000..020a8888 --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeSessionOptions.java @@ -0,0 +1,416 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.net.IpSecManager.UdpEncapsulationSocket; +import android.net.eap.EapSessionConfig; + +import com.android.internal.net.ipsec.ike.message.IkePayload; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.InetAddress; +import java.security.PrivateKey; +import java.security.cert.TrustAnchor; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.util.LinkedList; +import java.util.List; + +/** + * IkeSessionOptions contains all user provided configurations for negotiating an IKE SA. + * + *

TODO: Make this doc more user-friendly. + */ +public final class IkeSessionOptions { + @Retention(RetentionPolicy.SOURCE) + @IntDef({IKE_AUTH_METHOD_PSK, IKE_AUTH_METHOD_PUB_KEY_SIGNATURE, IKE_AUTH_METHOD_EAP}) + public @interface IkeAuthMethod {} + + // Constants to describe user configured authentication methods. + public static final int IKE_AUTH_METHOD_PSK = 1; + public static final int IKE_AUTH_METHOD_PUB_KEY_SIGNATURE = 2; + public static final int IKE_AUTH_METHOD_EAP = 3; + + private final InetAddress mServerAddress; + private final UdpEncapsulationSocket mUdpEncapSocket; + private final IkeSaProposal[] mSaProposals; + + private final IkeIdentification mLocalIdentification; + private final IkeIdentification mRemoteIdentification; + + private final IkeAuthConfig mLocalAuthConfig; + private final IkeAuthConfig mRemoteAuthConfig; + + private final boolean mIsIkeFragmentationSupported; + + private IkeSessionOptions( + InetAddress serverAddress, + UdpEncapsulationSocket udpEncapsulationSocket, + IkeSaProposal[] proposals, + IkeIdentification localIdentification, + IkeIdentification remoteIdentification, + IkeAuthConfig localAuthConfig, + IkeAuthConfig remoteAuthConfig, + boolean isIkeFragmentationSupported) { + mServerAddress = serverAddress; + mUdpEncapSocket = udpEncapsulationSocket; + mSaProposals = proposals; + + mLocalIdentification = localIdentification; + mRemoteIdentification = remoteIdentification; + + mLocalAuthConfig = localAuthConfig; + mRemoteAuthConfig = remoteAuthConfig; + + mIsIkeFragmentationSupported = isIkeFragmentationSupported; + } + + public InetAddress getServerAddress() { + return mServerAddress; + } + + public UdpEncapsulationSocket getUdpEncapsulationSocket() { + return mUdpEncapSocket; + } + + public IkeSaProposal[] getSaProposals() { + return mSaProposals; + } + + public IkeIdentification getLocalIdentification() { + return mLocalIdentification; + } + + public IkeIdentification getRemoteIdentification() { + return mRemoteIdentification; + } + + public IkeAuthConfig getLocalAuthConfig() { + return mLocalAuthConfig; + } + + public IkeAuthConfig getRemoteAuthConfig() { + return mRemoteAuthConfig; + } + + public boolean isIkeFragmentationSupported() { + return mIsIkeFragmentationSupported; + } + /** This class contains common information of an IKEv2 authentication configuration. */ + public abstract static class IkeAuthConfig { + @IkeAuthMethod public final int mAuthMethod; + + protected IkeAuthConfig(@IkeAuthMethod int authMethod) { + mAuthMethod = authMethod; + } + } + + /** + * This class represents the configuration to support IKEv2 pre-shared-key-based authentication + * of local or remote side. + */ + public static class IkeAuthPskConfig extends IkeAuthConfig { + public final byte[] mPsk; + + private IkeAuthPskConfig(byte[] psk) { + super(IKE_AUTH_METHOD_PSK); + mPsk = psk; + } + } + + /** + * This class represents the configuration to support IKEv2 public-key-signature-based + * authentication of the remote side. + */ + public static class IkeAuthDigitalSignRemoteConfig extends IkeAuthConfig { + public final TrustAnchor mTrustAnchor; + + private IkeAuthDigitalSignRemoteConfig(TrustAnchor trustAnchor) { + super(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE); + mTrustAnchor = trustAnchor; + } + } + + /** + * This class represents the configuration to support IKEv2 public-key-signature-based + * authentication of the local side. + */ + public static class IkeAuthDigitalSignLocalConfig extends IkeAuthConfig { + public final X509Certificate mEndCert; + public final List mIntermediateCerts; + public final PrivateKey mPrivateKey; + + private IkeAuthDigitalSignLocalConfig( + X509Certificate clientEndCert, + List clientIntermediateCerts, + PrivateKey privateKey) { + super(IKE_AUTH_METHOD_PUB_KEY_SIGNATURE); + mEndCert = clientEndCert; + mIntermediateCerts = clientIntermediateCerts; + mPrivateKey = privateKey; + } + } + + /** + * This class represents the configuration to support EAP authentication of the local side. + * + *

EAP MUST be used with IKEv2 public-key-based authentication of the responder to the + * initiator. Currently IKE library does not support the IKEv2 protocol extension(RFC 5998) + * which allows EAP methods that provide mutual authentication and key agreement to be used to + * provide extensible responder authentication for IKEv2 based on methods other than public key + * signatures. + * + * @see RFC 5998, An Extension for EAP-Only + * Authentication in IKEv2 + */ + public static class IkeAuthEapConfig extends IkeAuthConfig { + public final EapSessionConfig mEapConfig; + + private IkeAuthEapConfig(EapSessionConfig eapConfig) { + super(IKE_AUTH_METHOD_EAP); + + mEapConfig = eapConfig; + } + } + + /** This class can be used to incrementally construct a IkeSessionOptions. */ + public static final class Builder { + private final List mSaProposalList = new LinkedList<>(); + + private InetAddress mServerAddress; + private UdpEncapsulationSocket mUdpEncapSocket; + + private IkeIdentification mLocalIdentification; + private IkeIdentification mRemoteIdentification; + + private IkeAuthConfig mLocalAuthConfig; + private IkeAuthConfig mRemoteAuthConfig; + + private boolean mIsIkeFragmentationSupported = false; + + /** + * Sets server address + * + * @param serverAddress IP address of remote IKE server. + * @return Builder this, to facilitate chaining. + */ + public Builder setServerAddress(@NonNull InetAddress serverAddress) { + mServerAddress = serverAddress; + return this; + } + + /** + * Sets UDP-Encapsulated socket + * + * @param udpEncapsulationSocket {@link IpSecManager.UdpEncapsulationSocket} for sending and + * receiving IKE message. + * @return Builder this, to facilitate chaining. + */ + public Builder setUdpEncapsulationSocket( + @NonNull UdpEncapsulationSocket udpEncapsulationSocket) { + mUdpEncapSocket = udpEncapsulationSocket; + return this; + } + + /** + * Sets local IKE identification. + * + * @param identification the local IKE identification. + * @return Builder this, to facilitate chaining. + */ + public Builder setLocalIdentification(IkeIdentification identification) { + mLocalIdentification = identification; + return this; + } + + /** + * Sets remote IKE identification. + * + * @param identification the remote IKE identification. + * @return Builder this, to facilitate chaining. + */ + public Builder setRemoteIdentification(IkeIdentification identification) { + mRemoteIdentification = identification; + return this; + } + + /** + * Adds an IKE SA proposal to IkeSessionOptions being built. + * + * @param proposal IKE SA proposal. + * @return Builder this, to facilitate chaining. + * @throws IllegalArgumentException if input proposal is not IKE SA proposal. + */ + public Builder addSaProposal(IkeSaProposal proposal) { + if (proposal.getProtocolId() != IkePayload.PROTOCOL_ID_IKE) { + throw new IllegalArgumentException( + "Expected IKE SA Proposal but received Child SA proposal"); + } + mSaProposalList.add(proposal); + return this; + } + + /** + * Uses pre-shared key to do IKE authentication. + * + *

Both client and server MUST be authenticated using the provided shared key. IKE + * authentication will fail if the remote peer tries to use other authentication methods. + * + *

Users MUST declare only one authentication method. Calling this function will override + * the previously set authentication configuration. + * + * @param sharedKey the shared key. + * @return Builder this, to facilitate chaining. + */ + public Builder setAuthPsk(@NonNull byte[] sharedKey) { + mLocalAuthConfig = new IkeAuthPskConfig(sharedKey); + mRemoteAuthConfig = new IkeAuthPskConfig(sharedKey); + return this; + } + + /** + * Uses EAP to do IKE authentication. + * + *

EAP are typically used to authenticate the IKE client to the server. It MUST be used + * in conjunction with a public-key-signature-based authentication of the server to the + * client. + * + *

Users MUST declare only one authentication method. Calling this function will override + * the previously set authentication configuration. + * + * @see RFC 5280, Internet X.509 Public Key + * Infrastructure Certificate and Certificate Revocation List (CRL) Profile + * @param serverCaCert the CA certificate for validating the received server certificate(s). + * @return Builder this, to facilitate chaining. + */ + public Builder setAuthEap( + @NonNull X509Certificate serverCaCert, @NonNull EapSessionConfig eapConfig) { + mLocalAuthConfig = new IkeAuthEapConfig(eapConfig); + + // The name constraints extension, defined in RFC 5280, indicates a name space within + // which all subject names in subsequent certificates in a certification path MUST be + // located. + mRemoteAuthConfig = + new IkeAuthDigitalSignRemoteConfig( + new TrustAnchor(serverCaCert, null /*nameConstraints*/)); + + // TODO: Investigate if we need to support the name constraints extension. + + return this; + } + + /** + * Uses certificate and digital signature to do IKE authentication. + * + *

The public key included by the client end certificate and the signature private key + * MUST come from the same key pair. + * + *

The IKE library will use the strongest signature algorithm supported by both sides. + * + *

Currenly only RSA digital signature is supported. + * + * @param serverCaCert the CA certificate for validating the received server certificate(s). + * @param clientEndCert the end certificate for remote server to verify the locally + * generated signature. + * @param clientPrivateKey private key to generate outbound digital signature. Only {@link + * RSAPrivateKey} is supported. + * @return Builder this, to facilitate chaining. + */ + public Builder setAuthDigitalSignature( + @NonNull X509Certificate serverCaCert, + @NonNull X509Certificate clientEndCert, + @NonNull PrivateKey clientPrivateKey) { + return setAuthDigitalSignature( + serverCaCert, + clientEndCert, + new LinkedList(), + clientPrivateKey); + } + + /** + * Uses certificate and digital signature to do IKE authentication. + * + *

The public key included by the client end certificate and the signature private key + * MUST come from the same key pair. + * + *

The IKE library will use the strongest signature algorithm supported by both sides. + * + *

Currenly only RSA digital signature is supported. + * + * @param serverCaCert the CA certificate for validating the received server certificate(s). + * @param clientEndCert the end certificate for remote server to verify locally generated + * signature. + * @param clientIntermediateCerts intermediate certificates for the remote server to + * validate the end certificate. + * @param clientPrivateKey private key to generate outbound digital signature. Only {@link + * RSAPrivateKey} is supported. + * @return Builder this, to facilitate chaining. + */ + public Builder setAuthDigitalSignature( + @NonNull X509Certificate serverCaCert, + @NonNull X509Certificate clientEndCert, + @NonNull List clientIntermediateCerts, + @NonNull PrivateKey clientPrivateKey) { + if (!(clientPrivateKey instanceof RSAPrivateKey)) { + throw new IllegalArgumentException("Unsupported private key type"); + } + + mLocalAuthConfig = + new IkeAuthDigitalSignLocalConfig( + clientEndCert, clientIntermediateCerts, clientPrivateKey); + mRemoteAuthConfig = + new IkeAuthDigitalSignRemoteConfig( + new TrustAnchor(serverCaCert, null /*nameConstraints*/)); + return this; + } + + /** + * Validates, builds and returns the IkeSessionOptions + * + * @return IkeSessionOptions the validated IkeSessionOptions + * @throws IllegalArgumentException if no IKE SA proposal is provided + */ + public IkeSessionOptions build() { + if (mSaProposalList.isEmpty()) { + throw new IllegalArgumentException("IKE SA proposal not found"); + } + if (mServerAddress == null + || mUdpEncapSocket == null + || mLocalIdentification == null + || mRemoteIdentification == null + || mLocalAuthConfig == null + || mRemoteAuthConfig == null) { + throw new IllegalArgumentException("Necessary parameter missing."); + } + + return new IkeSessionOptions( + mServerAddress, + mUdpEncapSocket, + mSaProposalList.toArray(new IkeSaProposal[mSaProposalList.size()]), + mLocalIdentification, + mRemoteIdentification, + mLocalAuthConfig, + mRemoteAuthConfig, + mIsIkeFragmentationSupported); + } + + // TODO: add methods for supporting IKE fragmentation. + } +} diff --git a/src/java/android/net/ipsec/ike/IkeTrafficSelector.java b/src/java/android/net/ipsec/ike/IkeTrafficSelector.java new file mode 100644 index 00000000..65154b9d --- /dev/null +++ b/src/java/android/net/ipsec/ike/IkeTrafficSelector.java @@ -0,0 +1,373 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.IntDef; +import android.util.ArraySet; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.ipsec.ike.exceptions.InvalidSyntaxException; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.util.Objects; + +/** + * IkeTrafficSelector represents a Traffic Selector of a Child SA. + * + *

IkeTrafficSelector can be constructed by users for initiating Create Child exchange or be + * constructed from a decoded inbound Traffic Selector Payload. + * + * @see RFC 7296, Internet Key Exchange + * Protocol Version 2 (IKEv2) + */ +public final class IkeTrafficSelector { + + // IpProtocolId consists of standard IP Protocol IDs. + @Retention(RetentionPolicy.SOURCE) + @IntDef({IP_PROTOCOL_ID_UNSPEC, IP_PROTOCOL_ID_ICMP, IP_PROTOCOL_ID_TCP, IP_PROTOCOL_ID_UDP}) + public @interface IpProtocolId {} + + // Zero value is re-defined by IKE to indicate that all IP protocols are acceptable. + @VisibleForTesting static final int IP_PROTOCOL_ID_UNSPEC = 0; + @VisibleForTesting static final int IP_PROTOCOL_ID_ICMP = 1; + @VisibleForTesting static final int IP_PROTOCOL_ID_TCP = 6; + @VisibleForTesting static final int IP_PROTOCOL_ID_UDP = 17; + + private static final ArraySet IP_PROTOCOL_ID_SET = new ArraySet<>(); + + static { + IP_PROTOCOL_ID_SET.add(IP_PROTOCOL_ID_UNSPEC); + IP_PROTOCOL_ID_SET.add(IP_PROTOCOL_ID_ICMP); + IP_PROTOCOL_ID_SET.add(IP_PROTOCOL_ID_TCP); + IP_PROTOCOL_ID_SET.add(IP_PROTOCOL_ID_UDP); + } + + /** + * TrafficSelectorType consists of IKE standard Traffic Selector Types. + * + * @see Internet + * Key Exchange Version 2 (IKEv2) Parameters + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TRAFFIC_SELECTOR_TYPE_IPV4_ADDR_RANGE, TRAFFIC_SELECTOR_TYPE_IPV6_ADDR_RANGE}) + public @interface TrafficSelectorType {} + + public static final int TRAFFIC_SELECTOR_TYPE_IPV4_ADDR_RANGE = 7; + public static final int TRAFFIC_SELECTOR_TYPE_IPV6_ADDR_RANGE = 8; + + public static final int PORT_NUMBER_MIN = 0; + public static final int PORT_NUMBER_MAX = 65535; + + // TODO: Consider defining these constants in a central place in Connectivity. + private static final int IPV4_ADDR_LEN = 4; + private static final int IPV6_ADDR_LEN = 16; + + @VisibleForTesting static final int TRAFFIC_SELECTOR_IPV4_LEN = 16; + @VisibleForTesting static final int TRAFFIC_SELECTOR_IPV6_LEN = 40; + + public final int tsType; + public final int ipProtocolId; + public final int selectorLength; + public final int startPort; + public final int endPort; + public final InetAddress startingAddress; + public final InetAddress endingAddress; + + private IkeTrafficSelector( + int tsType, + int ipProtocolId, + int selectorLength, + int startPort, + int endPort, + InetAddress startingAddress, + InetAddress endingAddress) { + this.tsType = tsType; + this.ipProtocolId = ipProtocolId; + this.selectorLength = selectorLength; + this.startPort = startPort; + this.endPort = endPort; + this.startingAddress = startingAddress; + this.endingAddress = endingAddress; + } + + /** + * Construct an instance of IkeTrafficSelector for building an outbound IKE message. + * + * @param tsType the Traffic Selector type. + * @param startPort the smallest port number allowed by this Traffic Selector. + * @param endPort the largest port number allowed by this Traffic Selector. + * @param startingAddress the smallest address included in this Traffic Selector. + * @param endingAddress the largest address included in this Traffic Selector. + */ + public IkeTrafficSelector( + @TrafficSelectorType int tsType, + int startPort, + int endPort, + InetAddress startingAddress, + InetAddress endingAddress) { + + this.tsType = tsType; + this.ipProtocolId = IP_PROTOCOL_ID_UNSPEC; + + switch (tsType) { + case TRAFFIC_SELECTOR_TYPE_IPV4_ADDR_RANGE: + this.selectorLength = TRAFFIC_SELECTOR_IPV4_LEN; + + if (!(startingAddress instanceof Inet4Address) + || !(endingAddress instanceof Inet4Address)) { + throw new IllegalArgumentException( + "Invalid address range: TS_IPV4_ADDR_RANGE requires IPv4 addresses."); + } + + break; + case TRAFFIC_SELECTOR_TYPE_IPV6_ADDR_RANGE: + throw new UnsupportedOperationException("Do not support IPv6 Traffic Selector."); + // TODO: Support IPv6 Traffic Selector. + default: + throw new IllegalArgumentException("Unrecognized Traffic Selector type."); + } + + if (compareInetAddressTo(startingAddress, endingAddress) > 0) { + throw new IllegalArgumentException("Received invalid address range."); + } + + if (!isPortRangeValid(startPort, endPort)) { + throw new IllegalArgumentException( + "Invalid port range. startPort: " + startPort + " endPort: " + endPort); + } + + this.startPort = startPort; + this.endPort = endPort; + this.startingAddress = startingAddress; + this.endingAddress = endingAddress; + } + + /** + * Decode IkeTrafficSelectors from inbound Traffic Selector Payload. + * + *

This method is only called by IkeTsPayload when decoding inbound IKE message. + * + * @param numTs number or Traffic Selectors + * @param tsBytes encoded byte array of Traffic Selectors + * @return an array of decoded IkeTrafficSelectors + * @throws InvalidSyntaxException if received bytes are malformed. + */ + public static IkeTrafficSelector[] decodeIkeTrafficSelectors(int numTs, byte[] tsBytes) + throws InvalidSyntaxException { + IkeTrafficSelector[] tsArray = new IkeTrafficSelector[numTs]; + ByteBuffer inputBuffer = ByteBuffer.wrap(tsBytes); + + try { + for (int i = 0; i < numTs; i++) { + int tsType = Byte.toUnsignedInt(inputBuffer.get()); + switch (tsType) { + case TRAFFIC_SELECTOR_TYPE_IPV4_ADDR_RANGE: + tsArray[i] = decodeIpv4TrafficSelector(inputBuffer); + break; + case TRAFFIC_SELECTOR_TYPE_IPV6_ADDR_RANGE: + // TODO: Support it. + throw new UnsupportedOperationException("Cannot decode this type."); + default: + throw new InvalidSyntaxException( + "Invalid Traffic Selector type: " + tsType); + } + } + } catch (BufferOverflowException e) { + // Throw exception if any Traffic Selector has invalid length. + throw new InvalidSyntaxException(e); + } + + if (inputBuffer.remaining() != 0) { + throw new InvalidSyntaxException( + "Unexpected trailing characters of Traffic Selectors."); + } + + return tsArray; + } + + // Decode Traffic Selector using IPv4 address range from a ByteBuffer. A BufferOverflowException + // will be thrown and caught by method caller if operation reaches the input ByteBuffer's limit. + private static IkeTrafficSelector decodeIpv4TrafficSelector(ByteBuffer inputBuffer) + throws InvalidSyntaxException { + // Decode and validate IP Protocol ID + int ipProtocolId = Byte.toUnsignedInt(inputBuffer.get()); + if (!IP_PROTOCOL_ID_SET.contains(ipProtocolId)) { + throw new InvalidSyntaxException("Invalid IP Protocol ID."); + } + + // Decode and validate Selector Length + int tsLength = Short.toUnsignedInt(inputBuffer.getShort()); + if (TRAFFIC_SELECTOR_IPV4_LEN != tsLength) { + throw new InvalidSyntaxException("Invalid Traffic Selector Length."); + } + + // Decode and validate ports + int startPort = Short.toUnsignedInt(inputBuffer.getShort()); + int endPort = Short.toUnsignedInt(inputBuffer.getShort()); + if (!isPortRangeValid(startPort, endPort)) { + throw new InvalidSyntaxException( + "Received invalid port range. startPort: " + + startPort + + " endPort: " + + endPort); + } + + // Decode and validate IPv4 addresses + byte[] startAddressBytes = new byte[IPV4_ADDR_LEN]; + byte[] endAddressBytes = new byte[IPV4_ADDR_LEN]; + inputBuffer.get(startAddressBytes); + inputBuffer.get(endAddressBytes); + try { + Inet4Address startAddress = + (Inet4Address) (Inet4Address.getByAddress(startAddressBytes)); + Inet4Address endAddress = (Inet4Address) (Inet4Address.getByAddress(endAddressBytes)); + + // Validate address range. + if (compareInetAddressTo(startAddress, endAddress) > 0) { + throw new InvalidSyntaxException("Received invalid IPv4 address range."); + } + + return new IkeTrafficSelector( + TRAFFIC_SELECTOR_TYPE_IPV4_ADDR_RANGE, + ipProtocolId, + TRAFFIC_SELECTOR_IPV4_LEN, + startPort, + endPort, + startAddress, + endAddress); + } catch (ClassCastException | UnknownHostException | IllegalArgumentException e) { + throw new InvalidSyntaxException(e); + } + } + + // TODO: Add a method for decoding IPv6 traffic selector. + + // Validate port range. + private static boolean isPortRangeValid(int startPort, int endPort) { + return (startPort >= PORT_NUMBER_MIN + && startPort <= PORT_NUMBER_MAX + && endPort >= PORT_NUMBER_MIN + && endPort <= PORT_NUMBER_MAX + && startPort <= endPort); + } + + // Compare two InetAddresses. Return -1 if the first input is smaller; 1 if the second input is + // smaller; 0 if two addresses are equal. + // TODO: Consider moving it to the platform code in the future./ + private static int compareInetAddressTo(InetAddress leftAddress, InetAddress rightAddress) { + byte[] leftAddrBytes = leftAddress.getAddress(); + byte[] rightAddrBytes = rightAddress.getAddress(); + + if (leftAddrBytes.length != rightAddrBytes.length) { + throw new IllegalArgumentException("Two addresses are different types."); + } + + for (int i = 0; i < leftAddrBytes.length; i++) { + int unsignedByteLeft = Byte.toUnsignedInt(leftAddrBytes[i]); + int unsignedByteRight = Byte.toUnsignedInt(rightAddrBytes[i]); + + int result = Integer.compare(unsignedByteLeft, unsignedByteRight); + if (result != 0) return result; + } + return 0; + } + + /** + * Check if the input IkeTrafficSelector is a subset of this instance. + * + * @param ts the provided IkeTrafficSelector to check. + * @return true if the input IkeTrafficSelector is a subset of this instance, otherwise false. + */ + public boolean contains(IkeTrafficSelector ts) { + if (tsType == ts.tsType + && ipProtocolId == ts.ipProtocolId + && startPort <= ts.startPort + && endPort >= ts.endPort + && compareInetAddressTo(startingAddress, ts.startingAddress) <= 0 + && compareInetAddressTo(endingAddress, ts.endingAddress) >= 0) { + return true; + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash( + tsType, + ipProtocolId, + selectorLength, + startPort, + endPort, + startingAddress, + endingAddress); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof IkeTrafficSelector)) return false; + + IkeTrafficSelector other = (IkeTrafficSelector) o; + + if (tsType != other.tsType + || ipProtocolId != other.ipProtocolId + || startPort != other.startPort + || endPort != other.endPort) { + return false; + } + + switch (tsType) { + case TRAFFIC_SELECTOR_TYPE_IPV4_ADDR_RANGE: + return (((Inet4Address) startingAddress) + .equals((Inet4Address) other.startingAddress) + && ((Inet4Address) endingAddress) + .equals((Inet4Address) other.endingAddress)); + case TRAFFIC_SELECTOR_TYPE_IPV6_ADDR_RANGE: + return (((Inet6Address) startingAddress) + .equals((Inet6Address) other.startingAddress) + && ((Inet6Address) endingAddress) + .equals((Inet6Address) other.endingAddress)); + default: + throw new UnsupportedOperationException("Unrecognized TS type"); + } + } + + /** + * Encode traffic selector to ByteBuffer. + * + *

This method will be only called by IkeTsPayload for building an outbound IKE message. + * + * @param byteBuffer destination ByteBuffer that stores encoded traffic selector. + */ + public void encodeToByteBuffer(ByteBuffer byteBuffer) { + byteBuffer + .put((byte) tsType) + .put((byte) ipProtocolId) + .putShort((short) selectorLength) + .putShort((short) startPort) + .putShort((short) endPort) + .put(startingAddress.getAddress()) + .put(endingAddress.getAddress()); + } +} diff --git a/src/java/android/net/ipsec/ike/SaProposal.java b/src/java/android/net/ipsec/ike/SaProposal.java new file mode 100644 index 00000000..1e0b032e --- /dev/null +++ b/src/java/android/net/ipsec/ike/SaProposal.java @@ -0,0 +1,386 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.util.ArraySet; +import android.util.SparseArray; + +import com.android.internal.net.ipsec.ike.message.IkePayload; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.DhGroupTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EncryptionTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.IntegrityTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.PrfTransform; +import com.android.internal.net.ipsec.ike.message.IkeSaPayload.Transform; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** + * SaProposal represents a user configured set contains cryptograhic algorithms and key generating + * materials for negotiating an IKE or Child SA. + * + *

User must provide at least a valid SaProposal when they are creating a new IKE SA or Child SA. + * + * @see RFC 7296, Internet Key Exchange + * Protocol Version 2 (IKEv2) + */ +public abstract class SaProposal { + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + ENCRYPTION_ALGORITHM_3DES, + ENCRYPTION_ALGORITHM_AES_CBC, + ENCRYPTION_ALGORITHM_AES_GCM_8, + ENCRYPTION_ALGORITHM_AES_GCM_12, + ENCRYPTION_ALGORITHM_AES_GCM_16 + }) + public @interface EncryptionAlgorithm {} + + public static final int ENCRYPTION_ALGORITHM_3DES = 3; + public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; + public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; + public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; + public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; + + private static final SparseArray SUPPORTED_ENCRYPTION_ALGO_TO_STR; + + static { + SUPPORTED_ENCRYPTION_ALGO_TO_STR = new SparseArray<>(); + SUPPORTED_ENCRYPTION_ALGO_TO_STR.put(ENCRYPTION_ALGORITHM_3DES, "ENCR_3DES"); + SUPPORTED_ENCRYPTION_ALGO_TO_STR.put(ENCRYPTION_ALGORITHM_AES_CBC, "ENCR_AES_CBC"); + SUPPORTED_ENCRYPTION_ALGO_TO_STR.put(ENCRYPTION_ALGORITHM_AES_GCM_8, "ENCR_AES_GCM_8"); + SUPPORTED_ENCRYPTION_ALGO_TO_STR.put(ENCRYPTION_ALGORITHM_AES_GCM_12, "ENCR_AES_GCM_12"); + SUPPORTED_ENCRYPTION_ALGO_TO_STR.put(ENCRYPTION_ALGORITHM_AES_GCM_16, "ENCR_AES_GCM_16"); + } + + public static final int KEY_LEN_UNUSED = 0; + public static final int KEY_LEN_AES_128 = 128; + public static final int KEY_LEN_AES_192 = 192; + public static final int KEY_LEN_AES_256 = 256; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({PSEUDORANDOM_FUNCTION_HMAC_SHA1, PSEUDORANDOM_FUNCTION_AES128_XCBC}) + public @interface PseudorandomFunction {} + + public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; + public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; + + private static final SparseArray SUPPORTED_PRF_TO_STR; + + static { + SUPPORTED_PRF_TO_STR = new SparseArray<>(); + SUPPORTED_PRF_TO_STR.put(PSEUDORANDOM_FUNCTION_HMAC_SHA1, "PRF_HMAC_SHA1"); + SUPPORTED_PRF_TO_STR.put(PSEUDORANDOM_FUNCTION_AES128_XCBC, "PRF_AES128_XCBC"); + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + INTEGRITY_ALGORITHM_NONE, + INTEGRITY_ALGORITHM_HMAC_SHA1_96, + INTEGRITY_ALGORITHM_AES_XCBC_96, + INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, + INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, + INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 + }) + public @interface IntegrityAlgorithm {} + + public static final int INTEGRITY_ALGORITHM_NONE = 0; + public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; + public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; + public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; + public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; + public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; + + private static final SparseArray SUPPORTED_INTEGRITY_ALGO_TO_STR; + + static { + SUPPORTED_INTEGRITY_ALGO_TO_STR = new SparseArray<>(); + SUPPORTED_INTEGRITY_ALGO_TO_STR.put(INTEGRITY_ALGORITHM_NONE, "AUTH_NONE"); + SUPPORTED_INTEGRITY_ALGO_TO_STR.put(INTEGRITY_ALGORITHM_HMAC_SHA1_96, "AUTH_HMAC_SHA1_96"); + SUPPORTED_INTEGRITY_ALGO_TO_STR.put(INTEGRITY_ALGORITHM_AES_XCBC_96, "AUTH_AES_XCBC_96"); + SUPPORTED_INTEGRITY_ALGO_TO_STR.put( + INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, "AUTH_HMAC_SHA2_256_128"); + SUPPORTED_INTEGRITY_ALGO_TO_STR.put( + INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, "AUTH_HMAC_SHA2_384_192"); + SUPPORTED_INTEGRITY_ALGO_TO_STR.put( + INTEGRITY_ALGORITHM_HMAC_SHA2_512_256, "AUTH_HMAC_SHA2_512_256"); + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef({DH_GROUP_NONE, DH_GROUP_1024_BIT_MODP, DH_GROUP_2048_BIT_MODP}) + public @interface DhGroup {} + + public static final int DH_GROUP_NONE = 0; + public static final int DH_GROUP_1024_BIT_MODP = 2; + public static final int DH_GROUP_2048_BIT_MODP = 14; + + private static final SparseArray SUPPORTED_DH_GROUP_TO_STR; + + static { + SUPPORTED_DH_GROUP_TO_STR = new SparseArray<>(); + SUPPORTED_DH_GROUP_TO_STR.put(DH_GROUP_NONE, "DH_NONE"); + SUPPORTED_DH_GROUP_TO_STR.put(DH_GROUP_1024_BIT_MODP, "DH_1024_BIT_MODP"); + SUPPORTED_DH_GROUP_TO_STR.put(DH_GROUP_2048_BIT_MODP, "DH_2048_BIT_MODP"); + } + + @IkePayload.ProtocolId private final int mProtocolId; + private final EncryptionTransform[] mEncryptionAlgorithms; + private final IntegrityTransform[] mIntegrityAlgorithms; + private final DhGroupTransform[] mDhGroups; + + protected SaProposal( + @IkePayload.ProtocolId int protocol, + EncryptionTransform[] encryptionAlgos, + IntegrityTransform[] integrityAlgos, + DhGroupTransform[] dhGroups) { + mProtocolId = protocol; + mEncryptionAlgorithms = encryptionAlgos; + mIntegrityAlgorithms = integrityAlgos; + mDhGroups = dhGroups; + } + + /** + * Check if the current SaProposal from the SA responder is consistent with the selected + * reqProposal from the SA initiator. + * + * @param reqProposal selected SaProposal from SA initiator + * @return if current SaProposal from SA responder is consistent with the selected reqProposal + * from SA initiator. + */ + public boolean isNegotiatedFrom(SaProposal reqProposal) { + return this.mProtocolId == reqProposal.mProtocolId + && isTransformSelectedFrom(mEncryptionAlgorithms, reqProposal.mEncryptionAlgorithms) + && isTransformSelectedFrom(mIntegrityAlgorithms, reqProposal.mIntegrityAlgorithms) + && isTransformSelectedFrom(mDhGroups, reqProposal.mDhGroups); + } + + /** Package private */ + static boolean isTransformSelectedFrom(Transform[] selected, Transform[] selectFrom) { + // If the selected proposal has multiple transforms with the same type, the responder MUST + // choose a single one. + if ((selected.length > 1) || (selected.length == 0) != (selectFrom.length == 0)) { + return false; + } + + if (selected.length == 0) return true; + + return Arrays.asList(selectFrom).contains(selected[0]); + } + + @IkePayload.ProtocolId + public int getProtocolId() { + return mProtocolId; + } + + public EncryptionTransform[] getEncryptionTransforms() { + return mEncryptionAlgorithms; + } + + public IntegrityTransform[] getIntegrityTransforms() { + return mIntegrityAlgorithms; + } + + public DhGroupTransform[] getDhGroupTransforms() { + return mDhGroups; + } + + protected List getAllTransformsAsList() { + List transformList = new LinkedList<>(); + + transformList.addAll(Arrays.asList(mEncryptionAlgorithms)); + transformList.addAll(Arrays.asList(mIntegrityAlgorithms)); + transformList.addAll(Arrays.asList(mDhGroups)); + + return transformList; + } + + /** + * Return all SA Transforms in this SaProposal to be encoded for building an outbound IKE + * message. + * + *

This method should be called by only IKE library. + * + * @return Array of Transforms to be encoded. + */ + public abstract Transform[] getAllTransforms(); + + /** This class is an abstract Builder for building a SaProposal */ + protected abstract static class Builder { + protected static final String ERROR_TAG = "Invalid SA Proposal: "; + + // Use set to avoid adding repeated algorithms. + protected final Set mProposedEncryptAlgos = new ArraySet<>(); + protected final Set mProposedPrfs = new ArraySet<>(); + protected final Set mProposedIntegrityAlgos = new ArraySet<>(); + protected final Set mProposedDhGroups = new ArraySet<>(); + + protected boolean mHasAead = false; + + protected static boolean isAead(@EncryptionAlgorithm int algorithm) { + switch (algorithm) { + case ENCRYPTION_ALGORITHM_3DES: + // Fall through + case ENCRYPTION_ALGORITHM_AES_CBC: + return false; + case ENCRYPTION_ALGORITHM_AES_GCM_8: + // Fall through + case ENCRYPTION_ALGORITHM_AES_GCM_12: + // Fall through + case ENCRYPTION_ALGORITHM_AES_GCM_16: + return true; + default: + // Won't hit here. + throw new IllegalArgumentException("Unsupported Encryption Algorithm."); + } + } + + protected EncryptionTransform[] buildEncryptAlgosOrThrow() { + if (mProposedEncryptAlgos.isEmpty()) { + throw new IllegalArgumentException( + ERROR_TAG + "Encryption algorithm must be proposed."); + } + + return mProposedEncryptAlgos.toArray( + new EncryptionTransform[mProposedEncryptAlgos.size()]); + } + + protected void validateAndAddEncryptAlgo( + @EncryptionAlgorithm int algorithm, int keyLength) { + // Construct EncryptionTransform and validate proposed algorithm during + // construction. + EncryptionTransform encryptionTransform = new EncryptionTransform(algorithm, keyLength); + + // Validate that only one mode encryption algorithm has been proposed. + boolean isCurrentAead = isAead(algorithm); + if (!mProposedEncryptAlgos.isEmpty() && (mHasAead ^ isCurrentAead)) { + throw new IllegalArgumentException( + ERROR_TAG + + "Proposal cannot has both normal ciphers " + + "and combined-mode ciphers."); + } + if (isCurrentAead) mHasAead = true; + + mProposedEncryptAlgos.add(encryptionTransform); + } + + protected void addIntegrityAlgo(@IntegrityAlgorithm int algorithm) { + // Construct IntegrityTransform and validate proposed algorithm during + // construction. + mProposedIntegrityAlgos.add(new IntegrityTransform(algorithm)); + } + + protected void addDh(@DhGroup int dhGroup) { + // Construct DhGroupTransform and validate proposed dhGroup during + // construction. + mProposedDhGroups.add(new DhGroupTransform(dhGroup)); + } + } + + @Override + @NonNull + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(IkePayload.getProtocolTypeString(mProtocolId)).append(": "); + + int len = getAllTransforms().length; + for (int i = 0; i < len; i++) { + sb.append(getAllTransforms()[i].toString()); + if (i < len - 1) sb.append("|"); + } + + return sb.toString(); + } + + /** + * Check if the provided algorithm is a supported encryption algorithm. + * + * @param algorithm IKE standard encryption algorithm id. + * @return true if the provided algorithm is a supported encryption algorithm. + */ + public static boolean isSupportedEncryptionAlgorithm(@EncryptionAlgorithm int algorithm) { + return SUPPORTED_ENCRYPTION_ALGO_TO_STR.get(algorithm) != null; + } + + /** + * Check if the provided algorithm is a supported pseudorandom function. + * + * @param algorithm IKE standard pseudorandom function id. + * @return true if the provided algorithm is a supported pseudorandom function. + */ + public static boolean isSupportedPseudorandomFunction(@PseudorandomFunction int algorithm) { + return SUPPORTED_PRF_TO_STR.get(algorithm) != null; + } + + /** + * Check if the provided algorithm is a supported integrity algorithm. + * + * @param algorithm IKE standard integrity algorithm id. + * @return true if the provided algorithm is a supported integrity algorithm. + */ + public static boolean isSupportedIntegrityAlgorithm(@IntegrityAlgorithm int algorithm) { + return SUPPORTED_INTEGRITY_ALGO_TO_STR.get(algorithm) != null; + } + + /** + * Check if the provided group number is for a supported Diffie-Hellman Group. + * + * @param dhGroup IKE standard DH Group id. + * @return true if the provided number is for a supported Diffie-Hellman Group. + */ + public static boolean isSupportedDhGroup(@DhGroup int dhGroup) { + return SUPPORTED_DH_GROUP_TO_STR.get(dhGroup) != null; + } + + /** Return the encryption algorithm as a String. */ + public static String getEncryptionAlgorithmString(int algorithm) { + if (isSupportedEncryptionAlgorithm(algorithm)) { + return SUPPORTED_ENCRYPTION_ALGO_TO_STR.get(algorithm); + } + return "ENC_Unknown_" + algorithm; + } + + /** Return the pseudorandom function as a String. */ + public static String getPseudorandomFunctionString(int algorithm) { + if (isSupportedPseudorandomFunction(algorithm)) { + return SUPPORTED_PRF_TO_STR.get(algorithm); + } + return "PRF_Unknown_" + algorithm; + } + + /** Return the integrity algorithm as a String. */ + public static String getIntegrityAlgorithmString(int algorithm) { + if (isSupportedIntegrityAlgorithm(algorithm)) { + return SUPPORTED_INTEGRITY_ALGO_TO_STR.get(algorithm); + } + return "AUTH_Unknown_" + algorithm; + } + + /** Return Diffie-Hellman Group as a String. */ + public static String getDhGroupString(int dhGroup) { + if (isSupportedDhGroup(dhGroup)) { + return SUPPORTED_DH_GROUP_TO_STR.get(dhGroup); + } + return "DH_Unknown_" + dhGroup; + } +} diff --git a/src/java/android/net/ipsec/ike/TransportModeChildSessionOptions.java b/src/java/android/net/ipsec/ike/TransportModeChildSessionOptions.java new file mode 100644 index 00000000..12e0601a --- /dev/null +++ b/src/java/android/net/ipsec/ike/TransportModeChildSessionOptions.java @@ -0,0 +1,67 @@ +/* + * 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 android.net.ipsec.ike; + +import android.annotation.NonNull; + +/** + * This class contains all user provided configuration options for negotiating a transport mode + * Child Session. + */ +public final class TransportModeChildSessionOptions extends ChildSessionOptions { + private TransportModeChildSessionOptions( + IkeTrafficSelector[] localTs, + IkeTrafficSelector[] remoteTs, + ChildSaProposal[] proposals) { + super(localTs, remoteTs, proposals, true /*isTransport*/); + } + + /** This class can be used to incrementally construct a TransportModeChildSessionOptions. */ + public static final class Builder extends ChildSessionOptions.Builder { + /** Create a Builder for negotiating a transport mode Child Session. */ + public Builder() { + super(); + } + + /** + * Adds an Child SA proposal to TransportModeChildSessionOptions being built. + * + * @param proposal Child SA proposal. + * @return Builder this, to facilitate chaining. + * @throws IllegalArgumentException if input proposal is not a Child SA proposal. + */ + public Builder addSaProposal(@NonNull ChildSaProposal proposal) { + validateAndAddSaProposal(proposal); + return this; + } + + /** + * Validates, builds and returns the TransportModeChildSessionOptions. + * + * @return the validated TransportModeChildSessionOptions. + * @throws IllegalArgumentException if no Child SA proposal is provided. + */ + public TransportModeChildSessionOptions build() { + validateOrThrow(); + + return new TransportModeChildSessionOptions( + mLocalTsList.toArray(new IkeTrafficSelector[mLocalTsList.size()]), + mRemoteTsList.toArray(new IkeTrafficSelector[mRemoteTsList.size()]), + mSaProposalList.toArray(new ChildSaProposal[mSaProposalList.size()])); + } + } +} diff --git a/src/java/android/net/ipsec/ike/TunnelModeChildSessionOptions.java b/src/java/android/net/ipsec/ike/TunnelModeChildSessionOptions.java new file mode 100644 index 00000000..cb8268cf --- /dev/null +++ b/src/java/android/net/ipsec/ike/TunnelModeChildSessionOptions.java @@ -0,0 +1,260 @@ +/* + * 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 android.net.ipsec.ike; + +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; + +import android.annotation.NonNull; +import android.net.LinkAddress; + +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttribute; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Address; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Dhcp; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Dns; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Subnet; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Address; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Dns; +import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Subnet; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.util.LinkedList; +import java.util.List; + +/** + * This class contains all user provided configuration options for negotiating a tunnel mode Child + * Session. + */ +public final class TunnelModeChildSessionOptions extends ChildSessionOptions { + private final ConfigAttribute[] mConfigRequests; + + private TunnelModeChildSessionOptions( + IkeTrafficSelector[] localTs, + IkeTrafficSelector[] remoteTs, + ChildSaProposal[] proposals, + ConfigAttribute[] configRequests) { + super(localTs, remoteTs, proposals, false /*isTransport*/); + mConfigRequests = configRequests; + } + + public ConfigAttribute[] getConfigurationRequests() { + return mConfigRequests; + } + + /** This class can be used to incrementally construct a TunnelModeChildSessionOptions. */ + public static final class Builder extends ChildSessionOptions.Builder { + private static final int IPv4_DEFAULT_PREFIX_LEN = 32; + + private boolean mHasIp4AddressRequest; + private List mConfigRequestList; + + /** Create a Builder for negotiating a transport mode Child Session. */ + public Builder() { + super(); + mHasIp4AddressRequest = false; + mConfigRequestList = new LinkedList<>(); + } + + /** + * Adds an Child SA proposal to TunnelModeChildSessionOptions being built. + * + * @param proposal Child SA proposal. + * @return Builder this, to facilitate chaining. + * @throws IllegalArgumentException if input proposal is not a Child SA proposal. + */ + public Builder addSaProposal(@NonNull ChildSaProposal proposal) { + validateAndAddSaProposal(proposal); + return this; + } + + /** + * Adds internal IP address requests to TunnelModeChildSessionOptions being built. + * + * @param addressFamily the address family. Only {@link OsConstants.AF_INET} and {@link + * OsConstants.AF_INET6} are allowed. + * @param numOfRequest the number of requests for this type of address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalAddressRequest(int addressFamily, int numOfRequest) { + if (addressFamily == AF_INET) { + mHasIp4AddressRequest = true; + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv4Address()); + } + return this; + } else if (addressFamily == AF_INET6) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv6Address()); + } + return this; + } else { + throw new IllegalArgumentException("Invalid address family: " + addressFamily); + } + } + + /** + * Adds specific internal IP address request to TunnelModeChildSessionOptions being built. + * + * @param address the requested address. + * @param prefixLen length of the InetAddress prefix. When requesting an IPv4 address, + * prefixLen MUST be 32. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalAddressRequest(@NonNull InetAddress address, int prefixLen) { + if (address instanceof Inet4Address) { + if (prefixLen != IPv4_DEFAULT_PREFIX_LEN) { + throw new IllegalArgumentException("Invalid IPv4 prefix length: " + prefixLen); + } + mHasIp4AddressRequest = true; + mConfigRequestList.add(new ConfigAttributeIpv4Address((Inet4Address) address)); + return this; + } else if (address instanceof Inet6Address) { + mConfigRequestList.add( + new ConfigAttributeIpv6Address(new LinkAddress(address, prefixLen))); + return this; + } else { + throw new IllegalArgumentException("Invalid address " + address); + } + } + + /** + * Adds internal DNS server requests to TunnelModeChildSessionOptions being built. + * + * @param addressFamily the address family. Only {@link OsConstants.AF_INET} and {@link + * OsConstants.AF_INET6} are allowed. + * @param numOfRequest the number of requests for this type of address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalDnsServerRequest(int addressFamily, int numOfRequest) { + if (addressFamily == AF_INET) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv4Dns()); + } + return this; + } else if (addressFamily == AF_INET6) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv6Dns()); + } + return this; + } else { + throw new IllegalArgumentException("Invalid address family: " + addressFamily); + } + } + + /** + * Adds internal DNS server requests to TunnelModeChildSessionOptions being built. + * + * @param address the requested DNS server address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalDnsServerRequest(@NonNull InetAddress address) { + if (address instanceof Inet4Address) { + mConfigRequestList.add(new ConfigAttributeIpv4Dns((Inet4Address) address)); + return this; + } else if (address instanceof Inet6Address) { + mConfigRequestList.add(new ConfigAttributeIpv6Dns((Inet6Address) address)); + return this; + } else { + throw new IllegalArgumentException("Invalid address " + address); + } + } + + /** + * Adds internal subnet requests to TunnelModeChildSessionOptions being built. + * + * @param addressFamily the address family. Only {@link OsConstants.AF_INET} and {@link + * OsConstants.AF_INET6} are allowed. + * @param numOfRequest the number of requests for this type of address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalSubnetRequest(int addressFamily, int numOfRequest) { + if (addressFamily == AF_INET) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv4Subnet()); + } + return this; + } else if (addressFamily == AF_INET6) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv6Subnet()); + } + return this; + } else { + throw new IllegalArgumentException("Invalid address family: " + addressFamily); + } + } + + /** + * Adds internal DHCP server requests to TunnelModeChildSessionOptions being built. + * + *

Only DHCP4 server requests are supported. + * + * @param addressFamily the address family. Only {@link OsConstants.AF_INET} is allowed. + * @param numOfRequest the number of requests for this type of address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalDhcpServerRequest(int addressFamily, int numOfRequest) { + if (addressFamily == AF_INET) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv4Dhcp()); + } + return this; + } else { + throw new IllegalArgumentException("Invalid address family: " + addressFamily); + } + } + + /** + * Adds internal DHCP server requests to TunnelModeChildSessionOptions being built. + * + *

Only DHCP4 server requests are supported. + * + * @param address the requested DHCP server address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalDhcpServerRequest(@NonNull InetAddress address) { + if (address instanceof Inet4Address) { + mConfigRequestList.add(new ConfigAttributeIpv4Dhcp((Inet4Address) address)); + return this; + } else { + throw new IllegalArgumentException("Invalid address " + address); + } + } + + /** + * Validates, builds and returns the TunnelModeChildSessionOptions. + * + * @return the validated TunnelModeChildSessionOptions. + * @throws IllegalArgumentException if no Child SA proposal is provided. + */ + public TunnelModeChildSessionOptions build() { + validateOrThrow(); + + if (mHasIp4AddressRequest) { + mConfigRequestList.add(new ConfigAttributeIpv4Netmask()); + } + + return new TunnelModeChildSessionOptions( + mLocalTsList.toArray(new IkeTrafficSelector[mLocalTsList.size()]), + mRemoteTsList.toArray(new IkeTrafficSelector[mRemoteTsList.size()]), + mSaProposalList.toArray(new ChildSaProposal[mSaProposalList.size()]), + mConfigRequestList.toArray(new ConfigAttribute[mConfigRequestList.size()])); + } + } +} diff --git a/src/java/android/net/ipsec/ike/exceptions/IkeException.java b/src/java/android/net/ipsec/ike/exceptions/IkeException.java new file mode 100644 index 00000000..867dcf5e --- /dev/null +++ b/src/java/android/net/ipsec/ike/exceptions/IkeException.java @@ -0,0 +1,47 @@ +/* + * 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 android.net.ipsec.ike.exceptions; + +/** + * IkeException is a generic IKE library exception class that provides type safety for all the + * IKE-library-related exception classes that extend from it. + */ +public abstract class IkeException extends Exception { + protected IkeException() { + super(); + } + + protected IkeException(String message) { + super(message); + } + + protected IkeException(Throwable cause) { + super(cause); + } + + protected IkeException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Returns if this exception is caused by an IKE protocol error. + * + * @return true if this exception is caused by an IKE protocol error, false otherwise. + */ + public boolean isProtocolException() { + return this instanceof IkeProtocolException; + } +} diff --git a/src/java/android/net/ipsec/ike/exceptions/IkeInternalException.java b/src/java/android/net/ipsec/ike/exceptions/IkeInternalException.java new file mode 100644 index 00000000..29a5af94 --- /dev/null +++ b/src/java/android/net/ipsec/ike/exceptions/IkeInternalException.java @@ -0,0 +1,43 @@ +/* + * 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 android.net.ipsec.ike.exceptions; + +/** + * IkeInternalException represents all IKE-library-related exceptions that are not IKE protocol + * error. + */ +public final class IkeInternalException extends IkeException { + /** + * Constructs a new exception with the specified cause. + * + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} + * method). + */ + public IkeInternalException(Throwable cause) { + super(cause); + } + + /** + * Constructs a new exception with the specified cause. + * + * @param message the descriptive message. + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} + * method). + */ + public IkeInternalException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java b/src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java new file mode 100644 index 00000000..f589a267 --- /dev/null +++ b/src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java @@ -0,0 +1,182 @@ +/* + * 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 android.net.ipsec.ike.exceptions; + +import android.annotation.IntDef; + +import com.android.internal.net.ipsec.ike.message.IkeNotifyPayload; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.nio.ByteBuffer; + +/** + * IkeProtocolException is an abstract class that represents the common information for all IKE + * protocol errors. + * + * @see RFC 7296, Internet Key Exchange + * Protocol Version 2 (IKEv2) + */ +public abstract class IkeProtocolException extends IkeException { + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD, + ERROR_TYPE_INVALID_IKE_SPI, + ERROR_TYPE_INVALID_MAJOR_VERSION, + ERROR_TYPE_INVALID_SYNTAX, + ERROR_TYPE_INVALID_MESSAGE_ID, + ERROR_TYPE_NO_PROPOSAL_CHOSEN, + ERROR_TYPE_INVALID_KE_PAYLOAD, + ERROR_TYPE_AUTHENTICATION_FAILED, + ERROR_TYPE_SINGLE_PAIR_REQUIRED, + ERROR_TYPE_NO_ADDITIONAL_SAS, + ERROR_TYPE_INTERNAL_ADDRESS_FAILURE, + ERROR_TYPE_FAILED_CP_REQUIRED, + ERROR_TYPE_TS_UNACCEPTABLE, + ERROR_TYPE_INVALID_SELECTORS, + ERROR_TYPE_TEMPORARY_FAILURE, + ERROR_TYPE_CHILD_SA_NOT_FOUND, + }) + public @interface ErrorType {} + + public static final int ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1; + public static final int ERROR_TYPE_INVALID_IKE_SPI = 4; + public static final int ERROR_TYPE_INVALID_MAJOR_VERSION = 5; + public static final int ERROR_TYPE_INVALID_SYNTAX = 7; + public static final int ERROR_TYPE_INVALID_MESSAGE_ID = 9; + public static final int ERROR_TYPE_NO_PROPOSAL_CHOSEN = 14; + public static final int ERROR_TYPE_INVALID_KE_PAYLOAD = 17; + public static final int ERROR_TYPE_AUTHENTICATION_FAILED = 24; + public static final int ERROR_TYPE_SINGLE_PAIR_REQUIRED = 34; + public static final int ERROR_TYPE_NO_ADDITIONAL_SAS = 35; + public static final int ERROR_TYPE_INTERNAL_ADDRESS_FAILURE = 36; + public static final int ERROR_TYPE_FAILED_CP_REQUIRED = 37; + public static final int ERROR_TYPE_TS_UNACCEPTABLE = 38; + public static final int ERROR_TYPE_INVALID_SELECTORS = 39; + public static final int ERROR_TYPE_TEMPORARY_FAILURE = 43; + public static final int ERROR_TYPE_CHILD_SA_NOT_FOUND = 44; + + public static final byte[] ERROR_DATA_NOT_INCLUDED = new byte[0]; + + private static final int INTEGER_BYTE_SIZE = 4; + + @ErrorType private final int mErrorType; + private final byte[] mErrorData; + + protected IkeProtocolException(@ErrorType int code) { + super(); + mErrorType = code; + mErrorData = ERROR_DATA_NOT_INCLUDED; + } + + protected IkeProtocolException(@ErrorType int code, String message) { + super(message); + mErrorType = code; + mErrorData = ERROR_DATA_NOT_INCLUDED; + } + + protected IkeProtocolException(@ErrorType int code, Throwable cause) { + super(cause); + mErrorType = code; + mErrorData = ERROR_DATA_NOT_INCLUDED; + } + + protected IkeProtocolException(@ErrorType int code, String message, Throwable cause) { + super(message, cause); + mErrorType = code; + mErrorData = ERROR_DATA_NOT_INCLUDED; + } + + // Construct an instance from a notify Payload. + protected IkeProtocolException(@ErrorType int code, byte[] notifyData) { + super(); + + if (!isValidDataLength(notifyData.length)) { + throw new IllegalArgumentException( + "Invalid error data for error type: " + + code + + " Received error data size: " + + notifyData.length); + } + + mErrorType = code; + mErrorData = notifyData; + } + + protected abstract boolean isValidDataLength(int dataLen); + + protected static byte[] integerToByteArray(int integer, int arraySize) { + if (arraySize > INTEGER_BYTE_SIZE) { + throw new IllegalArgumentException( + "Cannot convert integer to a byte array of length: " + arraySize); + } + + ByteBuffer dataBuffer = ByteBuffer.allocate(INTEGER_BYTE_SIZE); + dataBuffer.putInt(integer); + dataBuffer.rewind(); + + byte[] zeroPad = new byte[INTEGER_BYTE_SIZE - arraySize]; + byte[] byteData = new byte[arraySize]; + dataBuffer.get(zeroPad).get(byteData); + + return byteData; + } + + protected static int byteArrayToInteger(byte[] byteArray) { + if (byteArray == null || byteArray.length > INTEGER_BYTE_SIZE) { + throw new IllegalArgumentException("Cannot convert the byte array to integer"); + } + + ByteBuffer dataBuffer = ByteBuffer.allocate(INTEGER_BYTE_SIZE); + byte[] zeroPad = new byte[INTEGER_BYTE_SIZE - byteArray.length]; + dataBuffer.put(zeroPad).put(byteArray); + dataBuffer.rewind(); + + return dataBuffer.getInt(); + } + + /** + * Returns the IKE standard protocol error type of this {@link IkeProtocolException} instance. + * + * @return the IKE standard protocol error type. + */ + @ErrorType + public int getErrorType() { + return mErrorType; + } + + /** + * Returns the included error data of this {@link IkeProtocolException} instance. + * + *

Note that only few error types will go with an error data. This data has different meaning + * with different error types. Users should first check if an error data is included before they + * call this method. + * + * @return the included error data in byte array. + */ + public byte[] getErrorData() { + return mErrorData; + } + + /** + * Build an IKE Notification Payload for this {@link IkeProtocolException} instance. + * + * @return the notification payload. + */ + public IkeNotifyPayload buildNotifyPayload() { + return new IkeNotifyPayload(mErrorType, mErrorData); + } +} diff --git a/src/java/com/android/ike/crypto/KeyGenerationUtils.java b/src/java/com/android/ike/crypto/KeyGenerationUtils.java deleted file mode 100644 index 5ac8c579..00000000 --- a/src/java/com/android/ike/crypto/KeyGenerationUtils.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.crypto; - -import java.nio.ByteBuffer; - -/** - * KeyGenerationUtils is a util class that contains utils for key generation needed by IKEv2 and - * EAP. - */ -public class KeyGenerationUtils { - /** - * Returns the derived pseudorandom number with the specified length by iteratively applying a - * PRF. - * - *

prf+(K, S) outputs a pseudorandom stream by using the PRF iteratively. In this way it can - * generate long enough keying material containing all the keys. - * - * @see RFC 7296 Internet Key - * Exchange Protocol Version 2 (IKEv2) 2.13. Generating Keying Material - * @param byteSigner the PRF used to sign the given data using the given key. - * @param keyBytes the key to sign data. - * @param dataToSign the data to be signed. - * @param keyMaterialLen the length of keying materials to be generated. - * @return the byte array of keying materials - */ - public static byte[] prfPlus( - ByteSigner byteSigner, byte[] keyBytes, byte[] dataToSign, int keyMaterialLen) { - ByteBuffer keyMatBuffer = ByteBuffer.allocate(keyMaterialLen); - - byte[] previousMac = new byte[0]; - final int padLen = 1; - byte padValue = 1; - - while (keyMatBuffer.remaining() > 0) { - ByteBuffer dataToSignBuffer = - ByteBuffer.allocate(previousMac.length + dataToSign.length + padLen); - dataToSignBuffer.put(previousMac).put(dataToSign).put(padValue); - - previousMac = byteSigner.signBytes(keyBytes, dataToSignBuffer.array()); - - keyMatBuffer.put( - previousMac, 0, Math.min(previousMac.length, keyMatBuffer.remaining())); - - padValue++; - } - - return keyMatBuffer.array(); - } - - /** - * ByteSigner is an interface to be used for implementing the byte-signing for generating keys - * using {@link KeyGenerationUtils#prfPlus(ByteSigner, byte[], byte[], int)}. - */ - public interface ByteSigner { - /** - * Signs the given data using the key given. - * - *

Caller is responsible for providing a valid key according to their use cases. - * - * @param keyBytes the key to sign data. - * @param dataToSign the data to be signed. - * @return the signed value. - */ - byte[] signBytes(byte[] keyBytes, byte[] dataToSign); - } -} diff --git a/src/java/com/android/ike/eap/EapAuthenticator.java b/src/java/com/android/ike/eap/EapAuthenticator.java deleted file mode 100644 index 463096ce..00000000 --- a/src/java/com/android/ike/eap/EapAuthenticator.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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.eap; - -import android.content.Context; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; - -import com.android.ike.eap.EapResult.EapError; -import com.android.ike.eap.EapResult.EapResponse; -import com.android.ike.eap.EapResult.EapSuccess; -import com.android.ike.eap.statemachine.EapStateMachine; -import com.android.ike.utils.Log; -import com.android.internal.annotations.VisibleForTesting; - -import java.security.SecureRandom; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeoutException; - -/** - * EapAuthenticator represents an EAP peer implementation. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ -public class EapAuthenticator extends Handler { - private static final String EAP_TAG = "EAP"; - private static final boolean LOG_SENSITIVE = false; - public static final Log LOG = new Log(EAP_TAG, LOG_SENSITIVE); - - private static final String TAG = EapAuthenticator.class.getSimpleName(); - private static final long DEFAULT_TIMEOUT_MILLIS = 7000L; - - private final Executor mWorkerPool; - private final EapStateMachine mStateMachine; - private final IEapCallback mCb; - private final long mTimeoutMillis; - private boolean mCallbackFired = false; - - /** - * Constructor for EapAuthenticator - * - * @param looper Looper for running a message loop - * @param cb IEapCallback for callbacks to the client - * @param context Context for this EapAuthenticator - * @param eapSessionConfig Configuration for an EapAuthenticator - */ - public EapAuthenticator( - Looper looper, - IEapCallback cb, - Context context, - EapSessionConfig eapSessionConfig) { - this( - looper, - cb, - new EapStateMachine(context, eapSessionConfig, new SecureRandom()), - Executors.newSingleThreadExecutor(), - DEFAULT_TIMEOUT_MILLIS); - } - - @VisibleForTesting - EapAuthenticator( - Looper looper, - IEapCallback cb, - EapStateMachine eapStateMachine, - Executor executor, - long timeoutMillis) { - super(looper); - - mCb = cb; - mStateMachine = eapStateMachine; - mWorkerPool = executor; - mTimeoutMillis = timeoutMillis; - } - - @Override - public void handleMessage(Message msg) { - // No messages processed here. Only runnables. Drop all messages. - } - - /** - * Processes the given msgBytes within the context of the current EAP Session. - * - *

If the given message is successfully processed, the relevant {@link IEapCallback} function - * is used. Otherwise, {@link IEapCallback#onError(Throwable)} is called. - * - * @param msgBytes the byte-array encoded EAP message to be processed - */ - public void processEapMessage(byte[] msgBytes) { - // reset - mCallbackFired = false; - - postDelayed( - () -> { - if (!mCallbackFired) { - // Fire failed callback - mCallbackFired = true; - LOG.e(TAG, "Timeout occurred in EapStateMachine"); - mCb.onError(new TimeoutException("Timeout while processing message")); - } - }, - EapAuthenticator.this, - mTimeoutMillis); - - // proxy to worker thread for async processing - mWorkerPool.execute( - () -> { - // Any unhandled exceptions within the state machine are caught here to make - // sure that the caller does not wait for the full timeout duration before being - // notified of a failure. - EapResult processResponse; - try { - processResponse = mStateMachine.process(msgBytes); - } catch (Exception ex) { - LOG.e(TAG, "Exception thrown while processing message", ex); - processResponse = new EapError(ex); - } - - final EapResult finalProcessResponse = processResponse; - EapAuthenticator.this.post( - () -> { - // No synchronization needed, since Handler serializes - if (!mCallbackFired) { - LOG.i( - TAG, - "EapStateMachine returned " - + finalProcessResponse - .getClass() - .getSimpleName()); - - if (finalProcessResponse instanceof EapResponse) { - mCb.onResponse(((EapResponse) finalProcessResponse).packet); - } else if (finalProcessResponse instanceof EapError) { - EapError eapError = (EapError) finalProcessResponse; - LOG.e( - TAG, - "EapError returned with cause=" + eapError.cause); - mCb.onError(eapError.cause); - } else if (finalProcessResponse instanceof EapSuccess) { - EapSuccess eapSuccess = (EapSuccess) finalProcessResponse; - LOG.d( - TAG, - "EapSuccess with" - + " MSK=" + LOG.pii(eapSuccess.msk) - + " EMSK=" + LOG.pii(eapSuccess.msk)); - mCb.onSuccess(eapSuccess.msk, eapSuccess.emsk); - } else { // finalProcessResponse instanceof EapFailure - mCb.onFail(); - } - - mCallbackFired = true; - - // Ensure delayed timeout runnable does not fire - EapAuthenticator.this.removeCallbacksAndMessages( - EapAuthenticator.this); - } - }); - }); - } -} diff --git a/src/java/com/android/ike/eap/EapResult.java b/src/java/com/android/ike/eap/EapResult.java deleted file mode 100644 index 0f97581f..00000000 --- a/src/java/com/android/ike/eap/EapResult.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.eap; - -import android.annotation.NonNull; - -import com.android.ike.eap.exceptions.InvalidEapResponseException; -import com.android.ike.eap.message.EapMessage; -import com.android.internal.annotations.VisibleForTesting; - -/** - * EapResult represents the return type R for a process operation within the EapStateMachine. - */ -public abstract class EapResult { - - /** - * EapSuccess represents a success response from the EapStateMachine. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ - public static class EapSuccess extends EapResult { - public final byte[] msk; - public final byte[] emsk; - - public EapSuccess(@NonNull byte[] msk, @NonNull byte[] emsk) { - if (msk == null || emsk == null) { - throw new IllegalArgumentException("msk and emsk must not be null"); - } - this.msk = msk; - this.emsk = emsk; - } - } - - /** - * EapFailure represents a failure response from the EapStateMachine. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ - public static class EapFailure extends EapResult {} - - /** - * EapResponse represents an outgoing message from the EapStateMachine. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ - public static class EapResponse extends EapResult { - public final byte[] packet; - - @VisibleForTesting - protected EapResponse(byte[] packet) { - this.packet = packet; - } - - /** - * Constructs and returns an EapResult for the given EapMessage. - * - *

If the given EapMessage is not of type EAP-Response, an EapError object will be - * returned. - * - * @param message the EapMessage to be encoded in the EapResponse instance. - * @return an EapResponse instance for the given message. If message.eapCode != {@link - * EapMessage#EAP_CODE_RESPONSE}, an EapError instance is returned. - */ - public static EapResult getEapResponse(@NonNull EapMessage message) { - if (message == null) { - throw new IllegalArgumentException("EapMessage should not be null"); - } else if (message.eapCode != EapMessage.EAP_CODE_RESPONSE) { - return new EapError(new InvalidEapResponseException( - "Cannot construct an EapResult from a non-EAP-Response message")); - } - - return new EapResponse(message.encode()); - } - } - - /** - * EapError represents an error that occurred in the EapStateMachine. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ - public static class EapError extends EapResult { - public final Exception cause; - - /** - * Constructs an EapError instance for the given cause. - * - * @param cause the Exception that caused the EapError to be returned from the - * EapStateMachine - */ - public EapError(Exception cause) { - this.cause = cause; - } - } -} diff --git a/src/java/com/android/ike/eap/EapSessionConfig.java b/src/java/com/android/ike/eap/EapSessionConfig.java deleted file mode 100644 index e3d77432..00000000 --- a/src/java/com/android/ike/eap/EapSessionConfig.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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.eap; - -import static com.android.ike.eap.message.EapData.EAP_TYPE_AKA; -import static com.android.ike.eap.message.EapData.EAP_TYPE_AKA_PRIME; -import static com.android.ike.eap.message.EapData.EAP_TYPE_MSCHAP_V2; -import static com.android.ike.eap.message.EapData.EAP_TYPE_SIM; - -import android.telephony.TelephonyManager.UiccAppType; - -import com.android.ike.eap.message.EapData.EapMethod; -import com.android.internal.annotations.VisibleForTesting; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * EapSessionConfig represents a container for EAP method configs to be used within an IKEv2 - * session. - * - *

The EAP authentication server decides which EAP method is used, so clients are encouraged to - * provide configs for several EAP methods. - */ -public final class EapSessionConfig { - @VisibleForTesting - static final byte[] DEFAULT_IDENTITY = new byte[0]; - - // IANA -> EapMethodConfig for that method - public final Map eapConfigs; - public final byte[] eapIdentity; - - @VisibleForTesting - public EapSessionConfig(Map eapConfigs, byte[] eapIdentity) { - this.eapConfigs = Collections.unmodifiableMap(eapConfigs); - this.eapIdentity = eapIdentity; - } - - /** This class can be used to incrementally construct an EapSessionConfig. */ - public static final class Builder { - private final Map mEapConfigs; - private byte[] mEapIdentity; - - /** - * Constructs and returns a new Builder for constructing an EapSessionConfig. - */ - public Builder() { - mEapConfigs = new HashMap<>(); - mEapIdentity = DEFAULT_IDENTITY; - } - - /** - * Sets the client's EAP Identity. - * - * @param eapIdentity byte[] representing the client's EAP Identity - * @return Builder this, to facilitate chaining. - */ - public Builder setEapIdentity(byte[] eapIdentity) { - this.mEapIdentity = eapIdentity.clone(); - return this; - } - - /** - * Sets the configuration for EAP SIM. - * - * @param subId int the client's subId to be authenticated - * @param apptype the {@link UiccAppType} apptype to be used for authentication - * @return Builder this, to facilitate chaining. - */ - public Builder setEapSimConfig(int subId, @UiccAppType int apptype) { - mEapConfigs.put(EAP_TYPE_SIM, new EapSimConfig(subId, apptype)); - return this; - } - - /** - * Sets the configuration for EAP AKA. - * - * @param subId int the client's subId to be authenticated - * @param apptype the {@link UiccAppType} apptype to be used for authentication - * @return Builder this, to facilitate chaining - */ - public Builder setEapAkaConfig(int subId, @UiccAppType int apptype) { - mEapConfigs.put(EAP_TYPE_AKA, new EapAkaConfig(subId, apptype)); - return this; - } - - /** - * Sets the configuration for EAP AKA'. - * - * @param subId int the client's subId to be authenticated - * @param apptype the {@link UiccAppType} apptype to be used for authentication - * @param networkName String the network name to be used for authentication. The String must - * be a UTF-8 String value - * @param allowMismatchedNetworkNames indicates whether the EAP library can ignore potential - * mismatches between the given network name and that received in an EAP-AKA' session. - * If false, mismatched network names will be handled as an Authentication Reject - * message. - * @return Builder this, to facilitate chaining - */ - public Builder setEapAkaPrimeConfig( - int subId, - @UiccAppType int apptype, - String networkName, - boolean allowMismatchedNetworkNames) { - mEapConfigs.put( - EAP_TYPE_AKA_PRIME, - new EapAkaPrimeConfig( - subId, apptype, networkName, allowMismatchedNetworkNames)); - return this; - } - - /** - * Sets the configuration for EAP MSCHAPv2. - * - * @param username String the client account's username to be authenticated - * @param password String the client account's password to be authenticated - * @return Builder this, to faciliate chaining - */ - public Builder setEapMsChapV2Config(String username, String password) { - mEapConfigs.put(EAP_TYPE_MSCHAP_V2, new EapMsChapV2Config(username, password)); - return this; - } - - /** - * Constructs and returns an EapSessionConfig with the configurations applied to this - * Builder. - * - * @return the EapSessionConfig constructed by this Builder - * @throws IllegalStateException iff no EAP methods have been configured - */ - public EapSessionConfig build() { - if (mEapConfigs.isEmpty()) { - throw new IllegalStateException("Must have at least one EAP method configured"); - } - - return new EapSessionConfig(mEapConfigs, mEapIdentity); - } - } - - /** EapMethodConfig represents a generic EAP method configuration. */ - public abstract static class EapMethodConfig { - @EapMethod public final int methodType; - - protected EapMethodConfig(@EapMethod int methodType) { - this.methodType = methodType; - } - } - - /** - * EapUiccConfig represents the configs needed for EAP methods that rely on UICC cards for - * authentication. - */ - public abstract static class EapUiccConfig extends EapMethodConfig { - public final int subId; - public final int apptype; - - private EapUiccConfig(@EapMethod int methodType, int subId, @UiccAppType int apptype) { - super(methodType); - this.subId = subId; - this.apptype = apptype; - } - } - - /** - * EapSimConfig represents the configs needed for an EAP SIM session. - */ - public static class EapSimConfig extends EapUiccConfig { - @VisibleForTesting - public EapSimConfig(int subId, @UiccAppType int apptype) { - super(EAP_TYPE_SIM, subId, apptype); - } - } - - /** - * EapAkaConfig represents the configs needed for an EAP AKA session. - */ - public static class EapAkaConfig extends EapUiccConfig { - @VisibleForTesting - public EapAkaConfig(int subId, @UiccAppType int apptype) { - super(EAP_TYPE_AKA, subId, apptype); - } - } - - /** - * EapAkaPrimeConfig represents the configs needed for an EAP-AKA' session. - */ - public static class EapAkaPrimeConfig extends EapAkaConfig { - public final String networkName; - public final boolean allowMismatchedNetworkNames; - - @VisibleForTesting - public EapAkaPrimeConfig( - int subId, - @UiccAppType int apptype, - String networkName, - boolean allowMismatchedNetworkNames) { - super(subId, apptype); - - this.networkName = networkName; - this.allowMismatchedNetworkNames = allowMismatchedNetworkNames; - } - } - - /** - * EapMsChapV2Config represents the configs needed for an EAP MSCHAPv2 session. - */ - public static class EapMsChapV2Config extends EapMethodConfig { - public final String username; - public final String password; - - @VisibleForTesting - public EapMsChapV2Config(String username, String password) { - super(EAP_TYPE_MSCHAP_V2); - - this.username = username; - this.password = password; - } - } -} diff --git a/src/java/com/android/ike/eap/IEapCallback.java b/src/java/com/android/ike/eap/IEapCallback.java deleted file mode 100644 index 7bd82016..00000000 --- a/src/java/com/android/ike/eap/IEapCallback.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.eap; - -/** - * IEapCallback represents a Callback interface to be implemented by clients of the - * {@link EapAuthenticator}. - * - *

Exactly one of these callbacks will be called for each message processed by the - * {@link EapAuthenticator}. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ -public interface IEapCallback { - /** - * Callback used to indicate that the EAP Authentication session was successful. - * - * @param msk The Master Session Key (MSK) generated in the session - * @param emsk The Extended Master Session Key (EMSK) generated in the session - */ - void onSuccess(byte[] msk, byte[] emsk); - - /** - * Callback used to indicate that the EAP Authentication Session was unsuccessful. - */ - void onFail(); - - /** - * Callback used to return an EAP-Response message for the message being processed. - * - * @param eapMsg byte-array encoded EAP-Response message to be sent to the Authentication server - */ - void onResponse(byte[] eapMsg); - - /** - * Callback used to indicate that there was an error processing the current EAP message. - * - * @param cause The cause of the processing error - */ - void onError(Throwable cause); -} diff --git a/src/java/com/android/ike/eap/crypto/Fips186_2Prf.java b/src/java/com/android/ike/eap/crypto/Fips186_2Prf.java deleted file mode 100644 index c98a406b..00000000 --- a/src/java/com/android/ike/eap/crypto/Fips186_2Prf.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.eap.crypto; - -import static com.android.ike.utils.BigIntegerUtils.bigIntegerToUnsignedByteArray; -import static com.android.ike.utils.BigIntegerUtils.unsignedByteArrayToBigInteger; - -import com.android.org.bouncycastle.crypto.digests.SHA1Digest; - -import java.math.BigInteger; -import java.nio.ByteBuffer; - -/** - * This class implements the Pseudo-Random Number Generator as specified by FIPS 186-2, change - * notice 1, as required by EAP-SIM (RFC 4186) and EAP-AKA (RFC 4187). - * - *

Simplifying constraints allow for some parameters to be permanently fixed: The "b" parameter - * is specified to always be 160 by RFC 4186. Likewise, the seed must be 20 bytes and therefore can - * never exceed 2^b. - */ -public class Fips186_2Prf { - private static final int SEED_LEN_BYTES = 20; - private static final int SHA_OUTPUT_LEN_BYTES = 40; - - /** - * Gets the next random based on the PRF described in FIPS 186-2, Change Notice 1. - * - * @param seed the seed value - * @param outputLenBytes the output byte count required. Will run multiple iterations as needed. - * @return the byte-array random result - */ - public byte[] getRandom(byte[] seed, int outputLenBytes) { - if (seed.length != SEED_LEN_BYTES) { - throw new IllegalArgumentException("Invalid seed length. Must be 160b (20B)"); - } - - BigInteger xkey = unsignedByteArrayToBigInteger(seed); - BigInteger exp_b = new BigInteger("2").pow(SEED_LEN_BYTES * 8); - - ByteBuffer buffer = ByteBuffer.allocate(outputLenBytes); - - // RFC 4186, Appendix B, Step 3: - // M is the number of generation runs, based on the desired output bytes (rounded up) - // EAP SIM/AKA require at least 16 (K_ENCR) + 16 (K_AUTH) + 64 (MSK) + 64 (EMSK) bytes - // (total 160 Bytes) - int numIterations = (outputLenBytes + SHA_OUTPUT_LEN_BYTES - 1) / SHA_OUTPUT_LEN_BYTES; - for (int j = 0; j < numIterations; j++) { - for (int i = 0; i < 2; i++) { - // RFC 4186, Appendix B, Step 3.1 XSEED_j = 0 - // (XSEED_j unused, omitted) - - // RFC 4186, Appendix B, Step 3.2a: XVAL = (XKEY + XSEED_j) mod 2^b - // (XSEED_j unused, omitted) - BigInteger xval = xkey.mod(exp_b); - - // RFC 4186, Appendix B, Step 3.2b: - // w_i = G(t, XVAL) - byte[] w_i = new byte[SEED_LEN_BYTES]; - Sha1_186_2_FunctionG digest = new Sha1_186_2_FunctionG(); - digest.update( - bigIntegerToUnsignedByteArray(xval, SEED_LEN_BYTES), 0, SEED_LEN_BYTES); - digest.doFinal(w_i, 0); - - // RFC 4186, Appendix B, Step 3.2c: - // XKEY = (1 + XKEY + w_i) mod 2^b - xkey = xkey.add(BigInteger.ONE).add(unsignedByteArrayToBigInteger(w_i)); - xkey = xkey.mod(exp_b); - - // RFC 4186, Appendix B, Step 3.3: - // x_j = w_0|w_1 - buffer.put(w_i, 0, Math.min(buffer.remaining(), w_i.length)); - } - } - - return buffer.array(); - } - - /** - * This inner class represents the modifications to the SHA1 digest required for FIPS 186-2 PRFs - * - *

FIPS 186-2 requires the use of a hashing function with exactly the same transforms as - * SHA1, but with a slightly different padding (all 0s instead of appending additional metadata - * for entropy). - * - *

Specifically, this function extends BouncyCastle's SHA1Digest in order to override the - * finish method, preventing the additional padding bytes from being appended (leaving them all - * 0). - */ - private static class Sha1_186_2_FunctionG extends SHA1Digest { - // IV (t) specified by SHA-1; Use default. - - @Override - public void finish() { - // Don't do any other processing. We only care about the processBlock() functionality. - processBlock(); - } - } -} diff --git a/src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java b/src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java deleted file mode 100644 index f5d4149f..00000000 --- a/src/java/com/android/ike/eap/crypto/HmacSha256ByteSigner.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.eap.crypto; - -import com.android.ike.crypto.KeyGenerationUtils; -import com.android.ike.crypto.KeyGenerationUtils.ByteSigner; - -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -/** - * HmacSha256ByteSigner is a {@link ByteSigner} to be used for computing HMAC-SHA-256 values for - * specific keys and data. - */ -public class HmacSha256ByteSigner implements KeyGenerationUtils.ByteSigner { - private static final String TAG = HmacSha256ByteSigner.class.getSimpleName(); - private static final String MAC_ALGORITHM_STRING = "HmacSHA256"; - private static final HmacSha256ByteSigner sInstance = new HmacSha256ByteSigner(); - - /** - * Gets instance of HmacSha256ByteSigner. - * - * @return HmacSha256ByteSigner instance. - */ - public static HmacSha256ByteSigner getInstance() { - return sInstance; - } - - @Override - public byte[] signBytes(byte[] keyBytes, byte[] dataToSign) { - try { - Mac mac = Mac.getInstance(MAC_ALGORITHM_STRING); - mac.init(new SecretKeySpec(keyBytes, MAC_ALGORITHM_STRING)); - return mac.doFinal(dataToSign); - } catch (NoSuchAlgorithmException | InvalidKeyException ex) { - throw new IllegalArgumentException(ex); - } - } -} diff --git a/src/java/com/android/ike/eap/crypto/ParityBitUtil.java b/src/java/com/android/ike/eap/crypto/ParityBitUtil.java deleted file mode 100644 index cf821e7c..00000000 --- a/src/java/com/android/ike/eap/crypto/ParityBitUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.eap.crypto; - -import com.android.internal.annotations.VisibleForTesting; - -/** - * This class sets parity-bits for a given byte-array as specified by the MSCHAPv2 standard. - * - * @see RFC 2759, Microsoft PPP CHAP Extensions, - * Version 2 (MSCHAPv2) - */ -public class ParityBitUtil { - private static final int INPUT_LENGTH = 7; - private static final int OUTPUT_LENGTH = 8; - private static final int BITS_PER_BYTE = 8; - private static final int BITS_PER_PARITY_BIT = 7; - private static final byte MASK = (byte) 0xFE; - - /** - * Computes and returns a byte[] with the odd-parity bits set. - * - *

Parity bits are set for the 8th, 16th, 24th, etc. bits as the LSB for each byte. - * - * @param input byte[] the input data requiring parity bits - * @return byte[] the input byte[] with its parity-bits set - * @throws IllegalArgumentException iff the given data array does not contain 7 bytes - */ - public static byte[] addParityBits(byte[] input) { - if (input.length != INPUT_LENGTH) { - throw new IllegalArgumentException("Data must be 7B long"); - } - byte[] output = new byte[OUTPUT_LENGTH]; - - long allBits = byteArrayToLong(input) << 1; // make room for parity bit - - // allBits stores input bits as [b56, ..., b1, 0]. Consuming allBits in reverse populates - // output with a right shift - for (int i = output.length - 1; i >= 0; i--) { - output[i] = getByteWithParityBit((byte) allBits); - allBits >>= BITS_PER_PARITY_BIT; - } - - return output; - } - - @VisibleForTesting - static byte getByteWithParityBit(byte b) { - // Parity bits per RFC 2759#8.6 - byte parity = - (byte) ((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ (b >> 1)); - - // If we have an odd number of bits, b1 should be 0. - // If we have an even number of bits, b1 should be 1. - byte parityBit = (byte) (~parity & 1); - return (byte) ((b & MASK) | parityBit); - } - - @VisibleForTesting - static long byteArrayToLong(byte[] input) { - long result = 0; - for (int i = 0; i < input.length; i++) { - result = (result << BITS_PER_BYTE) | Byte.toUnsignedInt(input[i]); - } - return result; - } -} diff --git a/src/java/com/android/ike/eap/exceptions/EapInvalidPacketLengthException.java b/src/java/com/android/ike/eap/exceptions/EapInvalidPacketLengthException.java deleted file mode 100644 index 4f8dff51..00000000 --- a/src/java/com/android/ike/eap/exceptions/EapInvalidPacketLengthException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.eap.exceptions; - -import com.android.ike.eap.message.EapMessage; - -/** - * This exception is thrown when the Packet Length for an {@link EapMessage} is invalid. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ -public class EapInvalidPacketLengthException extends EapSilentException { - /** - * Construct an instance of EapInvalidPacketLengthException with the specified detail message. - * - * @param message the detail message. - */ - public EapInvalidPacketLengthException(String message) { - super(message); - } - - /** - * Construct an instance of EapInvalidPacketLengthException with the specified message and - * cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapInvalidPacketLengthException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/EapInvalidRequestException.java b/src/java/com/android/ike/eap/exceptions/EapInvalidRequestException.java deleted file mode 100644 index 0e92587b..00000000 --- a/src/java/com/android/ike/eap/exceptions/EapInvalidRequestException.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.eap.exceptions; - -import com.android.ike.eap.statemachine.EapStateMachine; - -/** - * EapInvalidRequestException is thrown when invalid EapMessages are attempted to be processed by - * the {@link EapStateMachine}. - */ -public class EapInvalidRequestException extends Exception { - /** - * Construct an instance of EapInvalidRequestException with the specified detail message. - * - * @param message the detail message. - */ - public EapInvalidRequestException(String message) { - super(message); - } - - /** - * Construct an instance of EapInvalidRequestException with the specified message and cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapInvalidRequestException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/EapSilentException.java b/src/java/com/android/ike/eap/exceptions/EapSilentException.java deleted file mode 100644 index 08abfd2e..00000000 --- a/src/java/com/android/ike/eap/exceptions/EapSilentException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.eap.exceptions; - -/** - * EapSilentException represents a category of EAP errors that should be silently discarded by - * authenticators and peers. - * - *

EapSilentException is so-named due to its role in the EAP standard. RFC 3748 requires that - * several error cases be "silently discarded". In these cases, no EAP-Response message will be sent - * to the Authenticator. However, when thrown SilentExceptions will still signal an EAP failure to - * the IKE library calling it, resulting in an Authentication failure. - * - * Each type of silent error should implement its own subclass. - */ -public abstract class EapSilentException extends Exception { - /** - * Construct an instance of EapSilentException with the specified detail message. - * - * @param message the detail message. - */ - public EapSilentException(String message) { - super(message); - } - - /** - * Construct an instance of EapSilentException with the specified message and cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSilentException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/InvalidEapCodeException.java b/src/java/com/android/ike/eap/exceptions/InvalidEapCodeException.java deleted file mode 100644 index ee7c5286..00000000 --- a/src/java/com/android/ike/eap/exceptions/InvalidEapCodeException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.eap.exceptions; - -import com.android.ike.eap.message.EapMessage; - -/** - * This exception is thrown when the EAP Code for an {@link EapMessage} is invalid. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ -public class InvalidEapCodeException extends EapSilentException { - /** - * Construct an instance of InvalidEapCodeException with the specified code. - * - * @param code The invalid code type - */ - public InvalidEapCodeException(int code) { - super("Invalid Code included in EapMessage: " + code); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/InvalidEapResponseException.java b/src/java/com/android/ike/eap/exceptions/InvalidEapResponseException.java deleted file mode 100644 index 68b5e57d..00000000 --- a/src/java/com/android/ike/eap/exceptions/InvalidEapResponseException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.eap.exceptions; - -/** - * InvalidEapResponseException is thrown when an invalid EapResponse is attempted to be constructed. - * - *

EapResponses can only be constructed from EapMessages with the EAP Code for Responses (2). - */ -public class InvalidEapResponseException extends Exception { - - /** - * Construct an instance of InvalidEapResponseException with the specified detail message. - * - * @param message the detail message. - */ - public InvalidEapResponseException(String message) { - super(message); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/UnsupportedEapTypeException.java b/src/java/com/android/ike/eap/exceptions/UnsupportedEapTypeException.java deleted file mode 100644 index 1f36d441..00000000 --- a/src/java/com/android/ike/eap/exceptions/UnsupportedEapTypeException.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.eap.exceptions; - -import com.android.ike.eap.message.EapData.EapType; -import com.android.ike.eap.message.EapMessage; - -/** - * UnsupportedEapTypeException is thrown when an {@link EapMessage} is constructed with an - * unsupported {@link EapType} value. - */ -public class UnsupportedEapTypeException extends EapSilentException { - public final int eapIdentifier; - - /** - * Construct an instance of UnsupportedEapTypeException with the specified detail message. - * - * @param eapIdentifier the EAP Identifier for the message that contained the unsupported - * EapType - * @param message the detail message. - */ - public UnsupportedEapTypeException(int eapIdentifier, String message) { - super(message); - this.eapIdentifier = eapIdentifier; - } - - /** - * Construct an instance of UnsupportedEapTypeException with the specified message and cause. - * - * @param eapIdentifier the EAP Identifier for the message that contained the unsupported - * EapType - * @param message the detail message. - * @param cause the cause. - */ - public UnsupportedEapTypeException(int eapIdentifier, String message, Throwable cause) { - super(message, cause); - this.eapIdentifier = eapIdentifier; - } -} diff --git a/src/java/com/android/ike/eap/exceptions/mschapv2/EapMsChapV2ParsingException.java b/src/java/com/android/ike/eap/exceptions/mschapv2/EapMsChapV2ParsingException.java deleted file mode 100644 index 0da00759..00000000 --- a/src/java/com/android/ike/eap/exceptions/mschapv2/EapMsChapV2ParsingException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.eap.exceptions.mschapv2; - -/** - * EapMsChapV2ParsingException is thrown when an invalid MS-CHAPv2 Type Data is attempted to be - * processed. - */ -public class EapMsChapV2ParsingException extends Exception { - /** - * Construct an instance of EapMsChapV2ParsingException with the specified detail message. - * - * @param message the detail message. - */ - public EapMsChapV2ParsingException(String message) { - super(message); - } - - /** - * Construct an instance of EapMsChapV2ParsingException with the specified message and cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapMsChapV2ParsingException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapAkaInvalidAuthenticationResponse.java b/src/java/com/android/ike/eap/exceptions/simaka/EapAkaInvalidAuthenticationResponse.java deleted file mode 100644 index 8f81ed48..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapAkaInvalidAuthenticationResponse.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -/** - * EapAkaInvalidAuthenticationResponse is thrown when a UICC Challenge is processed during an - * EAP-AKA session and an invalid response format is returned. - */ -public class EapAkaInvalidAuthenticationResponse extends EapSimAkaAuthenticationFailureException { - /** - * Construct an instance of EapAkaInvalidAuthenticationResponse with the specified detail - * message. - * - * @param message the detail message. - */ - public EapAkaInvalidAuthenticationResponse(String message) { - super(message); - } - - /** - * Construct an instance of EapAkaInvalidAuthenticationResponse with the specified message and - * cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapAkaInvalidAuthenticationResponse(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaAuthenticationFailureException.java b/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaAuthenticationFailureException.java deleted file mode 100644 index 41950465..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaAuthenticationFailureException.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -/** - * EapSimAkaAuthenticationFailureException is thrown when an invalid Uicc Challenge is processed - * during an EAP-SIM or EAP-AKA session. - */ -public class EapSimAkaAuthenticationFailureException extends Exception { - /** - * Construct an instance of EapSimAkaAuthenticationFailureException with the specified detail - * message. - * - * @param message the detail message. - */ - public EapSimAkaAuthenticationFailureException(String message) { - super(message); - } - - /** - * Construct an instance of EapSimAkaAuthenticationFailureException with the specified message - * and cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSimAkaAuthenticationFailureException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaIdentityUnavailableException.java b/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaIdentityUnavailableException.java deleted file mode 100644 index c6e4a01d..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaIdentityUnavailableException.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -import android.telephony.TelephonyManager; - -/** - * EapSimAkaIdentityUnavailableException is thrown when the client's IMSI is unavailable from - * {@link TelephonyManager#getSubscriberId()}. - */ -public class EapSimAkaIdentityUnavailableException extends Exception { - /** - * Construct an instance of EapSimAkaIdentityUnavailableException with the specified detail - * message. - * - * @param message the detail message. - */ - public EapSimAkaIdentityUnavailableException(String message) { - super(message); - } - - /** - * Construct an instance of EapSimAkaIdentityUnavailableException with the specified message and - * cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSimAkaIdentityUnavailableException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidAtPaddingException.java b/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidAtPaddingException.java deleted file mode 100644 index e584444a..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidAtPaddingException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtPadding; - -/** - * EapSimAkaInvalidAtPaddingException is thrown when an {@link AtPadding} with invalid padding is - * parsed. Per RFC 4186#10.12 and RFC 4187#10.12, all padding bytes must be 0x00. - * - * @see RFC 4186, EAP-SIM, Section - * 10.12 - * @see RFC 4187, EAP-AKA, Section - * 10.12 - */ -public class EapSimAkaInvalidAtPaddingException extends EapSimAkaInvalidAttributeException { - /** - * Construct an instance of EapSimAkaInvalidAtPaddingException with the specified detail - * message. - * - * @param message the detail message. - */ - public EapSimAkaInvalidAtPaddingException(String message) { - super(message); - } - - /** - * Construct an instance of EapSimAkaInvalidAtPaddingException with the specified message and - * cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSimAkaInvalidAtPaddingException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidAttributeException.java b/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidAttributeException.java deleted file mode 100644 index 106dfb87..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidAttributeException.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -import com.android.ike.eap.message.simaka.EapSimAkaAttribute; - -/** - * EapSimAkaInvalidAttributeException is thrown when an invalid {@link EapSimAkaAttribute} is - * attempted to be parsed. - */ -public class EapSimAkaInvalidAttributeException extends Exception { - /** - * Construct an instance of EapSimAkaInvalidAttributeException with the specified detail - * message. - * - * @param message the detail message. - */ - public EapSimAkaInvalidAttributeException(String message) { - super(message); - } - - /** - * Construct an instance of EapSimAkaInvalidAttributeException with the specified message and - * cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSimAkaInvalidAttributeException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidLengthException.java b/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidLengthException.java deleted file mode 100644 index d4007884..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaInvalidLengthException.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -import android.telephony.TelephonyManager; - -/** - * EapSimAkaInvalidLengthException is thrown when - * {@link TelephonyManager#getIccAuthentication(int, int, String)} returns responses with the wrong - * lengths. - */ -public class EapSimAkaInvalidLengthException extends Exception { - /** - * Construct an instance of EapSimAkaInvalidLengthException with the specified detail message. - * - * @param message the detail message. - */ - public EapSimAkaInvalidLengthException(String message) { - super(message); - } - - /** - * Construct an instance of EapSimAkaInvalidLengthException with the specified message and - * cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSimAkaInvalidLengthException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaUnsupportedAttributeException.java b/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaUnsupportedAttributeException.java deleted file mode 100644 index 0731cff7..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapSimAkaUnsupportedAttributeException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -import com.android.ike.eap.message.simaka.EapSimAkaAttribute; -import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtVersionList; - -/** - * EapSimAkaUnsupportedAttributeException is thrown when an unsupported {@link EapSimAkaAttribute} - * is attempted to be decoded. - * - *

Attributes are supported or not supported per the EAP method being used. For example, an - * {@link AtVersionList} attribute would be considered "supported" when decoded from an EAP-SIM - * context, but would be considered "unsupported" from an EAP-AKA context. - */ -public class EapSimAkaUnsupportedAttributeException extends Exception { - /** - * Construct an instance of EapSimAkaUnsupportedAttributeException with the specified detail - * message. - * - * @param message the detail message. - */ - public EapSimAkaUnsupportedAttributeException(String message) { - super(message); - } - - /** - * Construct an instance of EapSimAkaUnsupportedAttributeException with the specified message - * and cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSimAkaUnsupportedAttributeException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapSimInvalidAtRandException.java b/src/java/com/android/ike/eap/exceptions/simaka/EapSimInvalidAtRandException.java deleted file mode 100644 index b01865a2..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapSimInvalidAtRandException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtRandSim; - -/** - * EapSimInvalidAtRandException is thrown when an {@link AtRandSim} with an invalid number of RAND - * values is parsed. When this error is encountered, an EAP-Response/SIM/Client-Error response must - * be used. Note that there MUST BE 2 or 3 RAND values for the AtRandSim to be considered valid. - * - * @see RFC 4186, EAP-SIM, Section - * 10.9 - */ -public class EapSimInvalidAtRandException extends EapSimAkaInvalidAttributeException { - /** - * Construct an instance of EapSimInvalidAtRandException with the specified detail message. - * - * @param message the detail message. - */ - public EapSimInvalidAtRandException(String message) { - super(message); - } - - /** - * Construct an instance of EapSimInvalidAtRandException with the specified message and - * cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSimInvalidAtRandException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/exceptions/simaka/EapSimInvalidTypeDataException.java b/src/java/com/android/ike/eap/exceptions/simaka/EapSimInvalidTypeDataException.java deleted file mode 100644 index 00152947..00000000 --- a/src/java/com/android/ike/eap/exceptions/simaka/EapSimInvalidTypeDataException.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.eap.exceptions.simaka; - -import com.android.ike.eap.message.simaka.EapSimTypeData; - -/** - * EapSimInvalidTypeDataException is thrown when invalid {@link EapSimTypeData} are attempted to be - * parsed. - */ -public class EapSimInvalidTypeDataException extends Exception { - /** - * Construct an instance of EapSimInvalidTypeDataException with the specified detail message. - * - * @param message the detail message. - */ - public EapSimInvalidTypeDataException(String message) { - super(message); - } - - /** - * Construct an instance of EapSimInvalidTypeDataException with the specified message and cause. - * - * @param message the detail message. - * @param cause the cause. - */ - public EapSimInvalidTypeDataException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/java/com/android/ike/eap/message/EapData.java b/src/java/com/android/ike/eap/message/EapData.java deleted file mode 100644 index 5e317160..00000000 --- a/src/java/com/android/ike/eap/message/EapData.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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.eap.message; - -import android.annotation.IntDef; -import android.annotation.NonNull; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -/** - * EapData represents the data-bytes of an EAP-Packet. - * - *

EapData objects will always have a Type-value and the Type-Data bytes that follow. - * - * EapData objects should be parsed from the Type and Type-Data sections of an EAP Packet, as shown - * below: - * - * +-----------------+-----------------+----------------------------------+ - * | Code (1B) | Identifier (1B) | Length (2B) | - * +-----------------+-----------------+----------------------------------+ - * | Type (1B) | Type-Data ... - * +-----------------+----- - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ -public class EapData { - @Retention(RetentionPolicy.SOURCE) - @IntDef({ - EAP_IDENTITY, - EAP_NOTIFICATION, - EAP_NAK, - EAP_TYPE_SIM, - EAP_TYPE_AKA, - EAP_TYPE_MSCHAP_V2, - EAP_TYPE_AKA_PRIME - }) - public @interface EapType {} - - @Retention(RetentionPolicy.SOURCE) - @IntDef({ - EAP_TYPE_SIM, - EAP_TYPE_AKA, - EAP_TYPE_MSCHAP_V2, - EAP_TYPE_AKA_PRIME - }) - public @interface EapMethod {} - - // EAP Type values defined by IANA - // https://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml - public static final int EAP_IDENTITY = 1; - public static final int EAP_NOTIFICATION = 2; - public static final int EAP_NAK = 3; - // EAP_MD5_CHALLENGE unsupported, allowable based on RFC 3748, Section 5.4 - public static final int EAP_TYPE_SIM = 18; - public static final int EAP_TYPE_AKA = 23; - public static final int EAP_TYPE_MSCHAP_V2 = 26; - public static final int EAP_TYPE_AKA_PRIME = 50; - - public static final Map EAP_TYPE_STRING = new HashMap<>(); - static { - EAP_TYPE_STRING.put(EAP_IDENTITY, "Identity"); - EAP_TYPE_STRING.put(EAP_NOTIFICATION, "Notification"); - EAP_TYPE_STRING.put(EAP_NAK, "Nak"); - EAP_TYPE_STRING.put(EAP_TYPE_SIM, "EAP-SIM"); - EAP_TYPE_STRING.put(EAP_TYPE_AKA, "EAP-AKA"); - EAP_TYPE_STRING.put(EAP_TYPE_MSCHAP_V2, "EAP-MSCHAP-V2"); - EAP_TYPE_STRING.put(EAP_TYPE_AKA_PRIME, "EAP-AKA-PRIME"); - } - - private static final Set SUPPORTED_TYPES = new HashSet<>(); - static { - SUPPORTED_TYPES.add(EAP_IDENTITY); - SUPPORTED_TYPES.add(EAP_NOTIFICATION); - SUPPORTED_TYPES.add(EAP_NAK); - - // supported EAP Method types - SUPPORTED_TYPES.add(EAP_TYPE_SIM); - SUPPORTED_TYPES.add(EAP_TYPE_AKA); - SUPPORTED_TYPES.add(EAP_TYPE_MSCHAP_V2); - SUPPORTED_TYPES.add(EAP_TYPE_AKA_PRIME); - } - - @EapType public final int eapType; - public final byte[] eapTypeData; - - public static final EapData NOTIFICATION_DATA = new EapData(EAP_NOTIFICATION, new byte[0]); - - /** - * Constructs a new EapData instance. - * - * @param eapType the {@link EapType} for this EapData instance - * @param eapTypeData the Type-Data for this EapData instance - * @throws IllegalArgumentException if eapTypeData is null or if - * {@link EapData#isSupportedEapType} is false for the given eapType - */ - public EapData(@EapType int eapType, @NonNull byte[] eapTypeData) { - this.eapType = eapType; - this.eapTypeData = eapTypeData; - - validate(); - } - - /** - * Gets the length of this EapData object. - * - * @return int for the number of bytes this EapData object represents - */ - public int getLength() { - // length of byte-array + 1 (for 1B type field) - return eapTypeData.length + 1; - } - - /** - * Returns whether this instance is equal to the given Object o. - * - * @param o the Object to be tested for equality - * @return true iff this instance is equal to the given o - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || !(o instanceof EapData)) { - return false; - } - EapData eapData = (EapData) o; - return eapType == eapData.eapType - && Arrays.equals(eapTypeData, eapData.eapTypeData); - } - - /** - * Returns the hashCode value for this instance. - * - * @return the hashCode value for this instance - */ - @Override - public int hashCode() { - return Objects.hash(eapType, Arrays.hashCode(eapTypeData)); - } - - /** - * Puts the byte-encoding for this EapData instance into the given ByteBuffer. - * - * @param b the ByteBuffer to write this EapData instance to - */ - public void encodeToByteBuffer(ByteBuffer b) { - b.put((byte) eapType); - b.put(eapTypeData); - } - - /** - * Returns whether the given eapType is a supported {@link EapType} value. - * - * @param eapType the value to be checked - * @return true iff the given eapType is a supported EAP Type - */ - public static boolean isSupportedEapType(int eapType) { - return SUPPORTED_TYPES.contains(eapType); - } - - private void validate() { - if (this.eapTypeData == null) { - throw new IllegalArgumentException("EapTypeData byte[] must be non-null"); - } - if (!isSupportedEapType(this.eapType)) { - throw new IllegalArgumentException("eapType must be be a valid @EapType value"); - } - } -} diff --git a/src/java/com/android/ike/eap/message/EapMessage.java b/src/java/com/android/ike/eap/message/EapMessage.java deleted file mode 100644 index 1f6cdfc3..00000000 --- a/src/java/com/android/ike/eap/message/EapMessage.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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.eap.message; - -import static com.android.ike.eap.EapAuthenticator.LOG; -import static com.android.ike.eap.message.EapData.EAP_NAK; -import static com.android.ike.eap.message.EapData.NOTIFICATION_DATA; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; - -import com.android.ike.eap.EapResult; -import com.android.ike.eap.EapResult.EapError; -import com.android.ike.eap.EapResult.EapResponse; -import com.android.ike.eap.exceptions.EapInvalidPacketLengthException; -import com.android.ike.eap.exceptions.EapSilentException; -import com.android.ike.eap.exceptions.InvalidEapCodeException; -import com.android.ike.eap.exceptions.UnsupportedEapTypeException; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * EapMessage represents an EAP Message. - * - *

EapMessages will be of type: - *

    - *
  • @{link EAP_CODE_REQUEST}
  • - *
  • @{link EAP_CODE_RESPONSE}
  • - *
  • @{link EAP_CODE_SUCCESS}
  • - *
  • @{link EAP_CODE_FAILURE}
  • - *
- * - * Per RFC 3748 Section 4, EAP-Request and EAP-Response packets should be in the format: - * - * +-----------------+-----------------+----------------------------------+ - * | Code (1B) | Identifier (1B) | Length (2B) | - * +-----------------+-----------------+----------------------------------+ - * | Type (1B) | Type-Data ... - * +-----------------+----- - * - * EAP-Success and EAP-Failure packets should be in the format: - * - * +-----------------+-----------------+----------------------------------+ - * | Code (1B) | Identifier (1B) | Length (2B) = '0004' | - * +-----------------+-----------------+----------------------------------+ - * - * Note that Length includes the EAP Header bytes. - * - * @see RFC 3748, Extensible Authentication - * Protocol (EAP) - */ -public class EapMessage { - private static final String TAG = EapMessage.class.getSimpleName(); - - @Retention(RetentionPolicy.SOURCE) - @IntDef({ - EAP_CODE_REQUEST, - EAP_CODE_RESPONSE, - EAP_CODE_SUCCESS, - EAP_CODE_FAILURE - }) - public @interface EapCode {} - - public static final int EAP_CODE_REQUEST = 1; - public static final int EAP_CODE_RESPONSE = 2; - public static final int EAP_CODE_SUCCESS = 3; - public static final int EAP_CODE_FAILURE = 4; - - public static final Map EAP_CODE_STRING = new HashMap<>(); - static { - EAP_CODE_STRING.put(EAP_CODE_REQUEST, "REQUEST"); - EAP_CODE_STRING.put(EAP_CODE_RESPONSE, "RESPONSE"); - EAP_CODE_STRING.put(EAP_CODE_SUCCESS, "SUCCESS"); - EAP_CODE_STRING.put(EAP_CODE_FAILURE, "FAILURE"); - } - - public static final int EAP_HEADER_LENGTH = 4; - - @EapCode public final int eapCode; - public final int eapIdentifier; - public final int eapLength; - public final EapData eapData; - - public EapMessage(@EapCode int eapCode, int eapIdentifier, @Nullable EapData eapData) - throws EapSilentException { - this.eapCode = eapCode; - this.eapIdentifier = eapIdentifier; - this.eapLength = EAP_HEADER_LENGTH + ((eapData == null) ? 0 : eapData.getLength()); - this.eapData = eapData; - - validate(); - } - - /** - * Decodes and returns an EapMessage from the given byte array. - * - * @param packet byte array containing a byte-encoded EapMessage - * @return the EapMessage instance representing the given {@param packet} - * @throws EapSilentException for decoding errors that must be discarded silently - */ - public static EapMessage decode(@NonNull byte[] packet) throws EapSilentException { - ByteBuffer buffer = ByteBuffer.wrap(packet); - int eapCode; - int eapIdentifier; - int eapLength; - EapData eapData; - try { - eapCode = Byte.toUnsignedInt(buffer.get()); - eapIdentifier = Byte.toUnsignedInt(buffer.get()); - eapLength = Short.toUnsignedInt(buffer.getShort()); - - if (eapCode == EAP_CODE_REQUEST || eapCode == EAP_CODE_RESPONSE) { - int eapType = Byte.toUnsignedInt(buffer.get()); - if (!EapData.isSupportedEapType(eapType)) { - LOG.e(TAG, "Decoding EAP packet with unsupported EAP-Type: " + eapType); - throw new UnsupportedEapTypeException(eapIdentifier, - "Unsupported eapType=" + eapType); - } - - byte[] eapDataBytes = new byte[buffer.remaining()]; - buffer.get(eapDataBytes); - eapData = new EapData(eapType, eapDataBytes); - } else { - eapData = null; - } - } catch (BufferUnderflowException ex) { - String msg = "EAP packet is missing required values"; - LOG.e(TAG, msg, ex); - throw new EapInvalidPacketLengthException(msg, ex); - } - - int eapDataLength = (eapData == null) ? 0 : eapData.getLength(); - if (eapLength > EAP_HEADER_LENGTH + eapDataLength) { - String msg = "Packet is shorter than specified length"; - LOG.e(TAG, msg); - throw new EapInvalidPacketLengthException(msg); - } - - return new EapMessage(eapCode, eapIdentifier, eapData); - } - - /** - * Converts this EapMessage instance to its byte-encoded representation. - * - * @return byte[] representing the byte-encoded EapMessage - */ - public byte[] encode() { - ByteBuffer byteBuffer = ByteBuffer.allocate(eapLength); - byteBuffer.put((byte) eapCode); - byteBuffer.put((byte) eapIdentifier); - byteBuffer.putShort((short) eapLength); - - if (eapData != null) { - eapData.encodeToByteBuffer(byteBuffer); - } - - return byteBuffer.array(); - } - - /** - * Creates and returns an EAP-Response/Notification message for the given EAP Identifier wrapped - * in an EapResponse object. - * - * @param eapIdentifier the identifier for the message being responded to - * @return an EapResponse object containing an EAP-Response/Notification message with an - * identifier matching the given identifier, or an EapError if an exception was thrown - */ - public static EapResult getNotificationResponse(int eapIdentifier) { - try { - return EapResponse.getEapResponse( - new EapMessage(EAP_CODE_RESPONSE, eapIdentifier, NOTIFICATION_DATA)); - } catch (EapSilentException ex) { - // this should never happen - the only variable value is the identifier - LOG.wtf(TAG, "Failed to create Notification Response for message with identifier=" - + eapIdentifier); - return new EapError(ex); - } - } - - /** - * Creates and returns an EAP-Response/Nak message for the given EAP Identifier wrapped in an - * EapResponse object. - * - * @param eapIdentifier the identifier for the message being responded to - * @param supportedEapTypes Collection of EAP Method types supported by the EAP Session - * @return an EapResponse object containing an EAP-Response/Nak message with an identifier - * matching the given identifier, or an EapError if an exception was thrown - */ - public static EapResult getNakResponse( - int eapIdentifier, - Collection supportedEapTypes) { - try { - ByteBuffer buffer = ByteBuffer.allocate(supportedEapTypes.size()); - for (int eapMethodType : supportedEapTypes) { - buffer.put((byte) eapMethodType); - } - EapData nakData = new EapData(EAP_NAK, buffer.array()); - - return EapResponse.getEapResponse( - new EapMessage(EAP_CODE_RESPONSE, eapIdentifier, nakData)); - } catch (EapSilentException ex) { - // this should never happen - the only variable value is the identifier - LOG.wtf(TAG, "Failed to create Nak for message with identifier=" - + eapIdentifier); - return new EapError(ex); - } - } - - private void validate() throws EapSilentException { - if (eapCode != EAP_CODE_REQUEST - && eapCode != EAP_CODE_RESPONSE - && eapCode != EAP_CODE_SUCCESS - && eapCode != EAP_CODE_FAILURE) { - LOG.e(TAG, "Invalid EAP Code: " + eapCode); - throw new InvalidEapCodeException(eapCode); - } - - if ((eapCode == EAP_CODE_SUCCESS || eapCode == EAP_CODE_FAILURE) - && eapLength != EAP_HEADER_LENGTH) { - LOG.e(TAG, "Invalid length for EAP-Success/EAP-Failure. Length: " + eapLength); - throw new EapInvalidPacketLengthException( - "EAP Success/Failure packets must be length 4"); - } - - if ((eapCode == EAP_CODE_REQUEST || eapCode == EAP_CODE_RESPONSE) && eapData == null) { - LOG.e(TAG, "No Type value included for EAP-Request/EAP-Response"); - throw new EapInvalidPacketLengthException( - "EAP Request/Response packets must include a Type value"); - } - } -} diff --git a/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2TypeData.java b/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2TypeData.java deleted file mode 100644 index a31f4a0c..00000000 --- a/src/java/com/android/ike/eap/message/mschapv2/EapMsChapV2TypeData.java +++ /dev/null @@ -1,600 +0,0 @@ -/* - * 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.eap.message.mschapv2; - -import static com.android.ike.eap.EapAuthenticator.LOG; - -import com.android.ike.eap.EapResult.EapError; -import com.android.ike.eap.exceptions.mschapv2.EapMsChapV2ParsingException; -import com.android.ike.eap.message.EapMessage; -import com.android.internal.annotations.VisibleForTesting; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * EapMsChapV2TypeData represents the Type Data for an {@link EapMessage} during an EAP MSCHAPv2 - * session. - */ -public class EapMsChapV2TypeData { - private static final int LABEL_VALUE_LENGTH = 2; - private static final String ASCII_CHARSET_NAME = "US-ASCII"; - private static final String MESSAGE_PREFIX = "M="; - private static final String MESSAGE_LABEL = "M"; - - // EAP MSCHAPv2 OpCode values (EAP MSCHAPv2#2) - public static final int EAP_MSCHAP_V2_CHALLENGE = 1; - public static final int EAP_MSCHAP_V2_RESPONSE = 2; - public static final int EAP_MSCHAP_V2_SUCCESS = 3; - public static final int EAP_MSCHAP_V2_FAILURE = 4; - public static final int EAP_MSCHAP_V2_CHANGE_PASSWORD = 7; - - public static final Map EAP_OP_CODE_STRING = new HashMap<>(); - static { - EAP_OP_CODE_STRING.put(EAP_MSCHAP_V2_CHALLENGE, "Challenge"); - EAP_OP_CODE_STRING.put(EAP_MSCHAP_V2_RESPONSE, "Response"); - EAP_OP_CODE_STRING.put(EAP_MSCHAP_V2_SUCCESS, "Success"); - EAP_OP_CODE_STRING.put(EAP_MSCHAP_V2_FAILURE, "Failure"); - EAP_OP_CODE_STRING.put(EAP_MSCHAP_V2_CHANGE_PASSWORD, "Change-Password"); - } - - private static final Set SUPPORTED_OP_CODES = new HashSet<>(); - static { - SUPPORTED_OP_CODES.add(EAP_MSCHAP_V2_CHALLENGE); - SUPPORTED_OP_CODES.add(EAP_MSCHAP_V2_RESPONSE); - SUPPORTED_OP_CODES.add(EAP_MSCHAP_V2_SUCCESS); - SUPPORTED_OP_CODES.add(EAP_MSCHAP_V2_FAILURE); - } - - public final int opCode; - - EapMsChapV2TypeData(int opCode) throws EapMsChapV2ParsingException { - this.opCode = opCode; - - if (!SUPPORTED_OP_CODES.contains(opCode)) { - throw new EapMsChapV2ParsingException("Unsupported opCode provided: " + opCode); - } - } - - /** - * Encodes this EapMsChapV2TypeData instance as a byte[]. - * - * @return byte[] representing the encoded value of this EapMsChapV2TypeData instance. - */ - public byte[] encode() { - throw new UnsupportedOperationException( - "encode() not supported by " + this.getClass().getSimpleName()); - } - - abstract static class EapMsChapV2VariableTypeData extends EapMsChapV2TypeData { - public final int msChapV2Id; - public final int msLength; - - EapMsChapV2VariableTypeData(int opCode, int msChapV2Id, int msLength) - throws EapMsChapV2ParsingException { - super(opCode); - - this.msChapV2Id = msChapV2Id; - this.msLength = msLength; - } - } - - /** - * EapMsChapV2ChallengeRequest represents the EAP MSCHAPv2 Challenge Packet (EAP MSCHAPv2#2.1). - */ - public static class EapMsChapV2ChallengeRequest extends EapMsChapV2VariableTypeData { - public static final int VALUE_SIZE = 16; - public static final int TYPE_DATA_HEADER_SIZE = 5; - - public final byte[] challenge = new byte[VALUE_SIZE]; - public final byte[] name; - - EapMsChapV2ChallengeRequest(ByteBuffer buffer) throws EapMsChapV2ParsingException { - super( - EAP_MSCHAP_V2_CHALLENGE, - Byte.toUnsignedInt(buffer.get()), - Short.toUnsignedInt(buffer.getShort())); - - int valueSize = Byte.toUnsignedInt(buffer.get()); - if (valueSize != VALUE_SIZE) { - throw new EapMsChapV2ParsingException("Challenge Value-Size must be 16"); - } - buffer.get(challenge); - - int nameLenBytes = msLength - VALUE_SIZE - TYPE_DATA_HEADER_SIZE; - if (nameLenBytes < 0) { - throw new EapMsChapV2ParsingException("Invalid MS-Length specified"); - } - - name = new byte[nameLenBytes]; - buffer.get(name); - } - - @VisibleForTesting - public EapMsChapV2ChallengeRequest( - int msChapV2Id, int msLength, byte[] challenge, byte[] name) - throws EapMsChapV2ParsingException { - super(EAP_MSCHAP_V2_CHALLENGE, msChapV2Id, msLength); - - if (challenge.length != VALUE_SIZE) { - throw new EapMsChapV2ParsingException("Challenge length must be 16"); - } - - System.arraycopy(challenge, 0, this.challenge, 0, VALUE_SIZE); - this.name = name; - } - } - - /** - * EapMsChapV2ChallengeResponse represents the EAP MSCHAPv2 Response Packet (EAP MSCHAPv2#2.2). - */ - public static class EapMsChapV2ChallengeResponse extends EapMsChapV2VariableTypeData { - public static final int VALUE_SIZE = 49; - public static final int PEER_CHALLENGE_SIZE = 16; - public static final int RESERVED_BYTES = 8; - public static final int NT_RESPONSE_SIZE = 24; - public static final int TYPE_DATA_HEADER_SIZE = 5; - - public final byte[] peerChallenge = new byte[PEER_CHALLENGE_SIZE]; - public final byte[] ntResponse = new byte[NT_RESPONSE_SIZE]; - public final int flags; - public final byte[] name; - - public EapMsChapV2ChallengeResponse( - int msChapV2Id, byte[] peerChallenge, byte[] ntResponse, int flags, byte[] name) - throws EapMsChapV2ParsingException { - super( - EAP_MSCHAP_V2_RESPONSE, - msChapV2Id, - TYPE_DATA_HEADER_SIZE + VALUE_SIZE + name.length); - - if (peerChallenge.length != PEER_CHALLENGE_SIZE) { - throw new EapMsChapV2ParsingException("Peer-Challenge must be 16B"); - } else if (ntResponse.length != NT_RESPONSE_SIZE) { - throw new EapMsChapV2ParsingException("NT-Response must be 24B"); - } else if (flags != 0) { - throw new EapMsChapV2ParsingException("Flags must be 0x00"); - } - - System.arraycopy(peerChallenge, 0, this.peerChallenge, 0, PEER_CHALLENGE_SIZE); - System.arraycopy(ntResponse, 0, this.ntResponse, 0, NT_RESPONSE_SIZE); - this.flags = flags; - this.name = name; - } - - @Override - public byte[] encode() { - ByteBuffer buffer = ByteBuffer.allocate(msLength); - buffer.put((byte) EAP_MSCHAP_V2_RESPONSE); - buffer.put((byte) msChapV2Id); - buffer.putShort((short) msLength); - buffer.put((byte) VALUE_SIZE); - buffer.put(peerChallenge); - buffer.put(new byte[RESERVED_BYTES]); - buffer.put(ntResponse); - buffer.put((byte) flags); - buffer.put(name); - - return buffer.array(); - } - } - - /** - * EapMsChapV2SuccessRequest represents the EAP MSCHAPv2 Success Request Packet - * (EAP MSCHAPv2#2.3). - */ - public static class EapMsChapV2SuccessRequest extends EapMsChapV2VariableTypeData { - private static final int AUTH_STRING_LEN_HEX = 40; - private static final int AUTH_STRING_LEN_BYTES = 20; - private static final int NUM_REQUIRED_ATTRIBUTES = 2; - private static final String AUTH_STRING_LABEL = "S"; - - public final byte[] authBytes = new byte[AUTH_STRING_LEN_BYTES]; - public final String message; - - EapMsChapV2SuccessRequest(ByteBuffer buffer) throws EapMsChapV2ParsingException { - super( - EAP_MSCHAP_V2_SUCCESS, - Byte.toUnsignedInt(buffer.get()), - Short.toUnsignedInt(buffer.getShort())); - - byte[] message = new byte[buffer.remaining()]; - buffer.get(message); - - // message formatting: "S= M=" - Map mappings = - getMessageMappings(new String(message, Charset.forName(ASCII_CHARSET_NAME))); - - if (!mappings.containsKey(AUTH_STRING_LABEL) - || mappings.size() != NUM_REQUIRED_ATTRIBUTES) { - throw new EapMsChapV2ParsingException( - "Auth message must be in the format: 'S= M='"); - } - - String authStringHex = mappings.get(AUTH_STRING_LABEL); - if (authStringHex.length() != AUTH_STRING_LEN_HEX) { - throw new EapMsChapV2ParsingException("Auth String must be 40 hex chars (20B)"); - } - byte[] authBytes = hexStringToByteArray(authStringHex); - System.arraycopy(authBytes, 0, this.authBytes, 0, AUTH_STRING_LEN_BYTES); - - this.message = mappings.get(MESSAGE_LABEL); - } - - @VisibleForTesting - public EapMsChapV2SuccessRequest( - int msChapV2Id, int msLength, byte[] authBytes, String message) - throws EapMsChapV2ParsingException { - super(EAP_MSCHAP_V2_SUCCESS, msChapV2Id, msLength); - - if (authBytes.length != AUTH_STRING_LEN_BYTES) { - throw new EapMsChapV2ParsingException("Auth String must be 20B"); - } - - System.arraycopy(authBytes, 0, this.authBytes, 0, AUTH_STRING_LEN_BYTES); - this.message = message; - } - } - - /** - * EapMsChapV2SuccessResponse represents the EAP MSCHAPv2 Success Response Packet - * (EAP MSCHAPv2#2.4). - */ - public static class EapMsChapV2SuccessResponse extends EapMsChapV2TypeData { - private EapMsChapV2SuccessResponse() throws EapMsChapV2ParsingException { - super(EAP_MSCHAP_V2_SUCCESS); - } - - /** - * Constructs and returns a new EAP MSCHAPv2 Success Response type data. - * - * @return a new EapMsChapV2SuccessResponse instance - */ - public static EapMsChapV2SuccessResponse getEapMsChapV2SuccessResponse() { - try { - return new EapMsChapV2SuccessResponse(); - } catch (EapMsChapV2ParsingException ex) { - // This should never happen - LOG.wtf( - EapMsChapV2SuccessResponse.class.getSimpleName(), - "ParsingException thrown while creating EapMsChapV2SuccessResponse", - ex); - return null; - } - } - - @Override - public byte[] encode() { - return new byte[] {(byte) EAP_MSCHAP_V2_SUCCESS}; - } - } - - /** - * EapMsChapV2FailureRequest represents the EAP MSCHAPv2 Failure Request Packet - * (EAP MSCHAPv2#2.5). - */ - public static class EapMsChapV2FailureRequest extends EapMsChapV2VariableTypeData { - private static final int NUM_REQUIRED_ATTRIBUTES = 5; - private static final int CHALLENGE_LENGTH = 16; - private static final String ERROR_LABEL = "E"; - private static final String RETRY_LABEL = "R"; - private static final String IS_RETRYABLE_FLAG = "1"; - private static final String CHALLENGE_LABEL = "C"; - private static final String PASSWORD_CHANGE_PROTOCOL_LABEL = "V"; - - // Error codes defined in EAP MSCHAPv2#2.5 - public static final Map EAP_ERROR_CODE_STRING = new HashMap<>(); - static { - EAP_ERROR_CODE_STRING.put(646, "ERROR_RESTRICTED_LOGON_HOURS"); - EAP_ERROR_CODE_STRING.put(647, "ERROR_ACCT_DISABLED"); - EAP_ERROR_CODE_STRING.put(648, "ERROR_PASSWD_EXPIRED"); - EAP_ERROR_CODE_STRING.put(649, "ERROR_NO_DIALIN_PERMISSION"); - EAP_ERROR_CODE_STRING.put(691, "ERROR_AUTHENTICATION_FAILURE"); - EAP_ERROR_CODE_STRING.put(709, "ERROR_CHANGING_PASSWORD"); - } - - public final int errorCode; - public final boolean isRetryable; - public final byte[] challenge; - public final int passwordChangeProtocol; - public final String message; - - EapMsChapV2FailureRequest(ByteBuffer buffer) - throws EapMsChapV2ParsingException, NumberFormatException { - super( - EAP_MSCHAP_V2_FAILURE, - Byte.toUnsignedInt(buffer.get()), - Short.toUnsignedInt(buffer.getShort())); - - byte[] message = new byte[buffer.remaining()]; - buffer.get(message); - - // message formatting: - // "E= R= C= V= M=" - Map mappings = - getMessageMappings(new String(message, Charset.forName(ASCII_CHARSET_NAME))); - if (!mappings.containsKey(ERROR_LABEL) - || !mappings.containsKey(RETRY_LABEL) - || !mappings.containsKey(CHALLENGE_LABEL) - || !mappings.containsKey(PASSWORD_CHANGE_PROTOCOL_LABEL) - || mappings.size() != NUM_REQUIRED_ATTRIBUTES) { - throw new EapMsChapV2ParsingException( - "Message must be formatted as: E= R= C=" - + " V= M="); - } - - this.errorCode = Integer.parseInt(mappings.get(ERROR_LABEL)); - this.isRetryable = IS_RETRYABLE_FLAG.equals(mappings.get(RETRY_LABEL)); - this.challenge = hexStringToByteArray(mappings.get(CHALLENGE_LABEL)); - this.passwordChangeProtocol = Integer.parseInt(mappings.get( - PASSWORD_CHANGE_PROTOCOL_LABEL)); - this.message = mappings.get("M"); - - if (challenge.length != CHALLENGE_LENGTH) { - throw new EapMsChapV2ParsingException("Challenge must be 16B long"); - } - } - - @VisibleForTesting - public EapMsChapV2FailureRequest( - int msChapV2Id, - int msLength, - int errorCode, - boolean isRetryable, - byte[] challenge, - int passwordChangeProtocol, - String message) - throws EapMsChapV2ParsingException { - super(EAP_MSCHAP_V2_FAILURE, msChapV2Id, msLength); - - this.errorCode = errorCode; - this.isRetryable = isRetryable; - this.challenge = challenge; - this.passwordChangeProtocol = passwordChangeProtocol; - this.message = message; - - if (challenge.length != CHALLENGE_LENGTH) { - throw new EapMsChapV2ParsingException("Challenge length must be 16B"); - } - } - } - - /** - * EapMsChapV2FailureResponse represents the EAP MSCHAPv2 Failure Response Packet - * (EAP MSCHAPv2#2.6). - */ - public static class EapMsChapV2FailureResponse extends EapMsChapV2TypeData { - private EapMsChapV2FailureResponse() throws EapMsChapV2ParsingException { - super(EAP_MSCHAP_V2_FAILURE); - } - - /** - * Constructs and returns a new EAP MSCHAPv2 Failure Response type data. - * - * @return a new EapMsChapV2FailureResponse instance - */ - public static EapMsChapV2FailureResponse getEapMsChapV2FailureResponse() { - try { - return new EapMsChapV2FailureResponse(); - } catch (EapMsChapV2ParsingException ex) { - // This should never happen - LOG.wtf( - EapMsChapV2SuccessResponse.class.getSimpleName(), - "ParsingException thrown while creating EapMsChapV2FailureResponse", - ex); - return null; - } - } - - @Override - public byte[] encode() { - return new byte[] {(byte) EAP_MSCHAP_V2_FAILURE}; - } - } - - @VisibleForTesting - static Map getMessageMappings(String message) - throws EapMsChapV2ParsingException { - Map messageMappings = new HashMap<>(); - int mPos = message.indexOf(MESSAGE_PREFIX); - - String preMString; - if (mPos == -1) { - preMString = message; - messageMappings.put(MESSAGE_LABEL, ""); - } else { - preMString = message.substring(0, mPos); - messageMappings.put(MESSAGE_LABEL, message.substring(mPos + MESSAGE_PREFIX.length())); - } - - // preMString: "S= " or "E= R=r C= V= " - for (String value : preMString.split(" ")) { - String[] keyValue = value.split("="); - if (keyValue.length != LABEL_VALUE_LENGTH) { - throw new EapMsChapV2ParsingException( - "Message must be formatted