Add end-to-end testing for EAP-AKA.
Bug: 140307380
Test: added EapAkaTest
Test: atest FrameworksIkeTests
Change-Id: I3c6ba7edcbef109cd0065f19511afa379af53776
diff --git a/src/java/com/android/ike/eap/message/simaka/EapAkaTypeData.java b/src/java/com/android/ike/eap/message/simaka/EapAkaTypeData.java
index ad310a3..381c538 100644
--- a/src/java/com/android/ike/eap/message/simaka/EapAkaTypeData.java
+++ b/src/java/com/android/ike/eap/message/simaka/EapAkaTypeData.java
@@ -102,7 +102,7 @@
TAG,
EAP_METHOD,
SUPPORTED_SUBTYPES,
- EapSimAttributeFactory.getInstance(),
+ EapAkaAttributeFactory.getInstance(),
EAP_AKA_SUBTYPE_STRING);
}
diff --git a/tests/iketests/src/java/com/android/ike/eap/EapAkaTest.java b/tests/iketests/src/java/com/android/ike/eap/EapAkaTest.java
new file mode 100644
index 0000000..a12128f
--- /dev/null
+++ b/tests/iketests/src/java/com/android/ike/eap/EapAkaTest.java
@@ -0,0 +1,292 @@
+/*
+ * 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_NOTIFICATION_PACKET;
+import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_REQUEST_SIM_START_PACKET;
+import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_RESPONSE_NOTIFICATION_PACKET;
+import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_SUCCESS;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.test.TestLooper;
+import android.telephony.TelephonyManager;
+
+import com.android.ike.eap.statemachine.EapStateMachine;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.SecureRandom;
+
+/**
+ * This test verifies that EAP-AKA is functional for an end-to-end implementation
+ */
+public class EapAkaTest {
+ private static final long AUTHENTICATOR_TIMEOUT_MILLIS = 250L;
+
+ private static final int SUB_ID = 1;
+ private static final String UNFORMATTED_IDENTITY = "123456789012345"; // IMSI
+
+ // TODO(b/140258387): replace with externally generated values
+ // TODO(b/140797965): find valid AUTN/RAND values for the CTS test sim
+ // IK: 0123456789ABCDEFFEDCBA9876543210
+ // CK: FEDCBA98765432100123456789ABCDEF
+ // MK: 342706B4C2632BFD61C3C16675DC3D719DDB7242
+ // K_encr: 6ACF941D8E5372A4876427F82BCB7009
+ // K_aut: 203FD02EB370465515BC5272E090D178
+ private static final String RAND_1 = "00112233445566778899AABBCCDDEEFF";
+ private static final String RAND_2 = "000102030405060708090A0B0C0D0E0F";
+ private static final String AUTN = "FFEEDDCCBBAA99887766554433221100";
+ private static final String RES = "00DEADBEEF";
+ private static final String AUTS = "0102030405060708090A0B0C0D0E";
+ private static final byte[] MSK =
+ hexStringToByteArray(
+ "91844F02FC56EBF0DFCF022224F9599F"
+ + "2D5C66A29002A182AF669C923AA1715C"
+ + "5BC14ABB672373631562E5F8BD494AA8"
+ + "66E54CB0518E95EE98EBA3D88D716C4D");
+ private static final byte[] EMSK =
+ hexStringToByteArray(
+ "8B04469725F115AA40C3065B3D8B4349"
+ + "18B31CD0C860D77CF42B7E94CE03A96B"
+ + "350511D8F49B0B1305BB693801E62995"
+ + "FAF04D26B49A4BD2587E1661B67B71C6");
+
+ // Base 64 of: [Length][RAND_1][Length][AUTN]
+ private static final String BASE64_CHALLENGE_1 =
+ "EAARIjNEVWZ3iJmqu8zd7v8Q/+7dzLuqmYh3ZlVEMyIRAA==";
+
+ // Base 64 of: ['DB'][Length][RES][Length][IK][Length][CK]
+ private static final String BASE_64_RESPONSE_SUCCESS =
+ "2wUA3q2+7xABI0VniavN7/7cuph2VDIQEP7cuph2VDIQASNFZ4mrze8=";
+
+ // Base 64 of: [Length][RAND_2][Length][AUTN]
+ private static final String BASE64_CHALLENGE_2 =
+ "EAABAgMEBQYHCAkKCwwNDg8Q/+7dzLuqmYh3ZlVEMyIRAA==";
+
+ // Base 64 of: ['DC'][Length][AUTS]
+ private static final String BASE_64_RESPONSE_SYNC_FAIL = "3A4BAgMEBQYHCAkKCwwNDg==";
+
+ private static final String REQUEST_MAC = "8BA174E3F5A3F758D027546214744868";
+ private static final String RESPONSE_MAC = "5a000bb376b37330f46482c6f6c4e536";
+
+ private static final byte[] EAP_AKA_IDENTITY_REQUEST =
+ hexStringToByteArray(
+ "0110000C" // EAP-Request | ID | length in bytes
+ + "17050000" // EAP-AKA | Identity | 2B padding
+ + "0D010000"); // AT_ANY_ID_REQ attribute
+ private static final byte[] EAP_AKA_IDENTITY_RESPONSE =
+ hexStringToByteArray(
+ "0210001C" // EAP-Response | ID | length in bytes
+ + "17050000" // EAP-AKA | Identity | 2B padding
+ + "0E05001030313233343536373839303132333435"); // AT_IDENTITY attribute
+
+ private static final byte[] EAP_AKA_CHALLENGE_REQUEST =
+ hexStringToByteArray(
+ "01110044" // EAP-Request | ID | length in bytes
+ + "17010000" // EAP-AKA | Challenge | 2B padding
+ + "01050000" + RAND_1 // AT_RAND attribute
+ + "02050000" + AUTN // AT_AUTN attribute
+ + "0B050000" + REQUEST_MAC); // AT_MAC attribute
+ private static final byte[] EAP_AKA_CHALLENGE_RESPONSE =
+ hexStringToByteArray(
+ "02110028" // EAP-Response | ID | length in bytes
+ + "17010000" // EAP-AKA | Challenge | 2B padding
+ + "03030028" + RES + "000000" // AT_RES attribute
+ + "0B050000" + RESPONSE_MAC); // AT_MAC attribute
+ private static final byte[] EAP_AKA_CHALLENGE_REQUEST_SYNC_FAIL =
+ hexStringToByteArray(
+ "01110044" // EAP-Request | ID | length in bytes
+ + "17010000" // EAP-AKA | Challenge | 2B padding
+ + "01050000" + RAND_2 // AT_RAND attribute
+ + "02050000" + AUTN // AT_AUTN attribute
+ + "0B050000" + REQUEST_MAC); // AT_MAC attribute
+ private static final byte[] EAP_AKA_SYNC_FAIL_RESPONSE =
+ hexStringToByteArray(
+ "02110018" // EAP-Response | ID | length in bytes
+ + "17040000" // EAP-AKA | Challenge | 2B padding
+ + "0404" + AUTS); // AT_AUTS attribute
+ private static final byte[] EAP_RESPONSE_NAK_PACKET =
+ hexStringToByteArray("021000060317"); // NAK with EAP-AKA listed
+
+ private Context mMockContext;
+ private TelephonyManager mMockTelephonyManager;
+ private SecureRandom mMockSecureRandom;
+ private IEapCallback mMockCallback;
+
+ private TestLooper mTestLooper;
+ private EapSessionConfig mEapSessionConfig;
+ private EapAuthenticator mEapAuthenticator;
+
+ @Before
+ public void setUp() {
+ mMockContext = mock(Context.class);
+ mMockTelephonyManager = mock(TelephonyManager.class);
+ mMockSecureRandom = mock(SecureRandom.class);
+ mMockCallback = mock(IEapCallback.class);
+
+ mTestLooper = new TestLooper();
+ mEapSessionConfig =
+ new EapSessionConfig.Builder().setEapAkaConfig(SUB_ID, APPTYPE_USIM).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 testEapAkaEndToEnd() {
+ verifyEapAkaIdentity();
+ verifyEapAkaChallenge();
+ verifyEapSuccess();
+ }
+
+ @Test
+ public void testEapAkaWithEapNotifications() {
+ verifyEapNotification(1);
+ verifyEapAkaIdentity();
+
+ verifyEapNotification(2);
+ verifyEapAkaChallenge();
+
+ verifyEapNotification(3);
+ verifyEapSuccess();
+ }
+
+ @Test
+ public void testEapAkaUnsupportedType() {
+ // EAP-Request/SIM/Start (unsupported type)
+ mEapAuthenticator.processEapMessage(EAP_REQUEST_SIM_START_PACKET);
+ mTestLooper.dispatchAll();
+
+ // verify EAP-Response/Nak returned
+ verify(mMockCallback).onResponse(eq(EAP_RESPONSE_NAK_PACKET));
+ verifyNoMoreInteractions(
+ mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback);
+
+ verifyEapAkaIdentity();
+ verifyEapAkaChallenge();
+ verifyEapSuccess();
+ }
+
+ @Test
+ public void testEapAkaSynchronizationFailure() {
+ verifyEapAkaIdentity();
+ verifyEapAkaSynchronizationFailure();
+ verifyEapAkaChallenge();
+ verifyEapSuccess();
+ }
+
+ private void verifyEapAkaIdentity() {
+ // EAP-AKA/Identity request
+ when(mMockTelephonyManager.getSubscriberId()).thenReturn(UNFORMATTED_IDENTITY);
+
+ mEapAuthenticator.processEapMessage(EAP_AKA_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_IDENTITY_RESPONSE));
+ verifyNoMoreInteractions(
+ mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback);
+ }
+
+ private void verifyEapAkaChallenge() {
+ // EAP-AKA/Challenge request
+ when(mMockTelephonyManager.getIccAuthentication(
+ TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_AKA,
+ BASE64_CHALLENGE_1))
+ .thenReturn(BASE_64_RESPONSE_SUCCESS);
+
+ mEapAuthenticator.processEapMessage(EAP_AKA_CHALLENGE_REQUEST);
+ mTestLooper.dispatchAll();
+
+ // verify EAP-AKA/Challenge response
+ verify(mMockTelephonyManager)
+ .getIccAuthentication(
+ TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_AKA,
+ BASE64_CHALLENGE_1);
+ verify(mMockCallback).onResponse(eq(EAP_AKA_CHALLENGE_RESPONSE));
+ verifyNoMoreInteractions(
+ mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback);
+ }
+
+ private void verifyEapAkaSynchronizationFailure() {
+ // EAP-AKA/Challenge request
+ when(mMockTelephonyManager.getIccAuthentication(
+ TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_AKA,
+ BASE64_CHALLENGE_2))
+ .thenReturn(BASE_64_RESPONSE_SYNC_FAIL);
+
+ mEapAuthenticator.processEapMessage(EAP_AKA_CHALLENGE_REQUEST_SYNC_FAIL);
+ mTestLooper.dispatchAll();
+
+ // verify EAP-AKA/Synchronization-Failure response
+ verify(mMockTelephonyManager)
+ .getIccAuthentication(
+ TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_AKA,
+ BASE64_CHALLENGE_2);
+ verify(mMockCallback).onResponse(eq(EAP_AKA_SYNC_FAIL_RESPONSE));
+ verifyNoMoreInteractions(
+ mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback);
+ }
+
+ private void verifyEapSuccess() {
+ // EAP-Success
+ mEapAuthenticator.processEapMessage(EAP_SUCCESS);
+ mTestLooper.dispatchAll();
+
+ // verify that onSuccess callback made
+ verify(mMockCallback).onSuccess(eq(MSK), eq(EMSK));
+ verifyNoMoreInteractions(
+ mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback);
+ }
+
+ private void verifyEapNotification(int callsToVerify) {
+ mEapAuthenticator.processEapMessage(EAP_REQUEST_NOTIFICATION_PACKET);
+ mTestLooper.dispatchAll();
+
+ verify(mMockCallback, times(callsToVerify))
+ .onResponse(eq(EAP_RESPONSE_NOTIFICATION_PACKET));
+ verifyNoMoreInteractions(
+ mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback);
+ }
+}
diff --git a/tests/iketests/src/java/com/android/ike/eap/EapSimTest.java b/tests/iketests/src/java/com/android/ike/eap/EapSimTest.java
index 9051d1d..ed69163 100644
--- a/tests/iketests/src/java/com/android/ike/eap/EapSimTest.java
+++ b/tests/iketests/src/java/com/android/ike/eap/EapSimTest.java
@@ -23,6 +23,7 @@
import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_REQUEST_NOTIFICATION_PACKET;
import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_RESPONSE_NAK_PACKET;
import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_RESPONSE_NOTIFICATION_PACKET;
+import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_SUCCESS;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -95,7 +96,6 @@
private static final byte[] EAP_SIM_CHALLENGE_RESPONSE = hexStringToByteArray(
"0286001c120b0000" // EAP header
+ "0b050000e5df9cb1d935ea5f54d449a038bed061"); // AT_NAC attribute
- private static final byte[] EAP_SUCCESS = hexStringToByteArray("03860004");
private Context mMockContext;
private TelephonyManager mMockTelephonyManager;
diff --git a/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java b/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java
index 999e502..5af5647 100644
--- a/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java
+++ b/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java
@@ -230,4 +230,6 @@
+ "17010000" // EAP-AKA | Challenge | 2B padding
+ "03030028" + RES + "000000" // AT_RES attribute
+ "0B050000" + EAP_AKA_CHALLENGE_RESPONSE_MAC); // AT_MAC attribute
+
+ public static final byte[] EAP_SUCCESS = hexStringToByteArray("03860004");
}