aboutsummaryrefslogtreecommitdiff
path: root/tests/iketests/src/java/com/android/internal/net/eap/EapAkaTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'tests/iketests/src/java/com/android/internal/net/eap/EapAkaTest.java')
-rw-r--r--tests/iketests/src/java/com/android/internal/net/eap/EapAkaTest.java332
1 files changed, 332 insertions, 0 deletions
diff --git a/tests/iketests/src/java/com/android/internal/net/eap/EapAkaTest.java b/tests/iketests/src/java/com/android/internal/net/eap/EapAkaTest.java
new file mode 100644
index 00000000..e982a85d
--- /dev/null
+++ b/tests/iketests/src/java/com/android/internal/net/eap/EapAkaTest.java
@@ -0,0 +1,332 @@
+/*
+ * 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.internal.net.eap;
+
+import static android.telephony.TelephonyManager.APPTYPE_USIM;
+
+import static com.android.internal.net.TestUtils.hexStringToByteArray;
+import static com.android.internal.net.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.net.eap.EapSessionConfig;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.net.eap.statemachine.EapStateMachine;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * This test verifies that EAP-AKA is functional for an end-to-end implementation
+ */
+public class EapAkaTest 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");
+
+ // TODO(b/140797965): find valid AUTN/RAND values for the CTS test sim
+ // IK: 7320EE404E055EF2B5AB0F86E96C48BE
+ // CK: E9D1707652E13BF3E05975F601678E5C
+ // MK: 2AE8AD50432246E6ACED9AA0FC794A22CE9CE4BB
+ // K_encr: DB6F06910D5D19CC9DA5F2687F5C5737
+ // K_aut: B20A586592796E08E7408FB53356E9B1
+ 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(
+ "EFC4FB9F54D99A3F4A04B756993CA813"
+ + "E463CA0ADBF3CB2A296519ED4C600FF5"
+ + "81898B1C425C20FE7471FC43A4BB3C00"
+ + "DDF80A7083972B660BC7153CBF2C9AA1");
+ private static final byte[] EMSK =
+ hexStringToByteArray(
+ "5C95F3E2476ED4D6588CE6DE2618D808"
+ + "9ECA12A4636C8A1B0C678562CBFC31D3"
+ + "94B578DE0A3686E17F96F14D5341FE75"
+ + "2012944CA394E5288BA1B2C70CB65063");
+
+ // IK: 7320EE404E055EF2B5AB0F86E96C48BE
+ // CK: E9D1707652E13BF3E05975F601678E5C
+ // MK: 8183017CD8ADDB4617F4A2274DD5BCEA99354FB7
+ // K_encr: 891D5DB8CACAF657D68BE72371F927A2
+ // K_aut: E042A1CC5672358685EC012881EA02DE
+ private static final byte[] MSK_WITHOUT_IDENTITY_REQ =
+ hexStringToByteArray(
+ "629DE03704E15EF1B8BADFF7FA5D84D5"
+ + "8574B6A3A46F274796346A86AE3455AC"
+ + "711E2D4D3F96EE71E664B1B947D7E9E7"
+ + "D227CBB6199A68BD7D43E6E4863D08D6");
+ private static final byte[] EMSK_WITHOUT_IDENTITY_REQ =
+ hexStringToByteArray(
+ "30A6638AE3AB5C5D29554D8256C3A287"
+ + "FDF6255E4D726C0622DDF89609C16A8D"
+ + "563768166A8111A083547DE4C8E280D6"
+ + "113A608DE9227FC7C02679A1E04DB3CF");
+
+ // 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 = "90C3554783D49A18F9EAA231F3C261EC";
+ private static final String RESPONSE_MAC = "D085987D3D15FA50A80D0CECFA2412EB";
+ private static final String REQUEST_MAC_WITHOUT_IDENTITY_REQ =
+ "6AD7E3F43ED99384E751F55AB8EA48B4";
+ private static final String RESPONSE_MAC_WITHOUT_IDENTITY_REQ =
+ "83E9F5B8B44BDE39B50538BF49864209";
+
+ private static final byte[] EAP_AKA_IDENTITY_REQUEST =
+ hexStringToByteArray(
+ "01CD000C" // 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(
+ "02CD001C" // EAP-Response | ID | length in bytes
+ + "17050000" // EAP-AKA | Identity | 2B padding
+ + "0E05001030313233343536373839414243444546"); // AT_IDENTITY attribute
+
+ private static final byte[] EAP_AKA_CHALLENGE_REQUEST =
+ hexStringToByteArray(
+ "01CE0044" // 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(
+ "02CE0030" // EAP-Response | ID | length in bytes
+ + "17010000" // EAP-AKA | Challenge | 2B padding
+ + "03050080" + RES // AT_RES attribute
+ + "0B050000" + RESPONSE_MAC); // AT_MAC attribute
+
+ private static final byte[] EAP_AKA_CHALLENGE_REQUEST_WITHOUT_IDENTITY_REQ =
+ hexStringToByteArray(
+ "01CE0044" // 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_WITHOUT_IDENTITY_REQ); // AT_MAC attribute
+ private static final byte[] EAP_AKA_CHALLENGE_RESPONSE_WITHOUT_IDENTITY_REQUEST =
+ hexStringToByteArray(
+ "02CE0030" // EAP-Response | ID | length in bytes
+ + "17010000" // 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_CHALLENGE_REQUEST_SYNC_FAIL =
+ hexStringToByteArray(
+ "01CE0044" // 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(
+ "02CE0018" // EAP-Response | ID | length in bytes
+ + "17040000" // EAP-AKA | Synchronization-Failure | 2B padding
+ + "0404" + AUTS); // AT_AUTS attribute
+
+ private static final byte[] EAP_AKA_AUTHENTICATION_REJECT =
+ hexStringToByteArray(
+ "02CE0008" // EAP-Response | ID | length in bytes
+ + "17020000"); // EAP-AKA | Authentication-Reject | 2B padding
+
+ private static final byte[] EAP_RESPONSE_NAK_PACKET =
+ hexStringToByteArray("021000060317"); // NAK with EAP-AKA listed
+
+ private TelephonyManager mMockTelephonyManager;
+
+ @Before
+ @Override
+ public void setUp() {
+ super.setUp();
+
+ mMockTelephonyManager = mock(TelephonyManager.class);
+
+ mEapSessionConfig =
+ new EapSessionConfig.Builder()
+ .setEapIdentity(EAP_IDENTITY)
+ .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(BASE_64_RESPONSE_SUCCESS, EAP_AKA_CHALLENGE_RESPONSE);
+ verifyEapSuccess(MSK, EMSK);
+ }
+
+ @Test
+ public void testEapAkaEndToEndWithoutIdentityRequest() {
+ verifyEapAkaChallengeWithoutIdentityReq();
+ verifyEapSuccess(MSK_WITHOUT_IDENTITY_REQ, EMSK_WITHOUT_IDENTITY_REQ);
+ }
+
+ @Test
+ public void testEapAkaWithEapNotifications() {
+ verifyEapNotification(1);
+ verifyEapAkaIdentity();
+
+ verifyEapNotification(2);
+ verifyEapAkaChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_CHALLENGE_RESPONSE);
+
+ verifyEapNotification(3);
+ verifyEapSuccess(MSK, EMSK);
+ }
+
+ @Test
+ public void testEapAkaUnsupportedType() {
+ verifyUnsupportedType(EAP_REQUEST_SIM_START_PACKET, EAP_RESPONSE_NAK_PACKET);
+
+ verifyEapAkaIdentity();
+ verifyEapAkaChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_CHALLENGE_RESPONSE);
+ verifyEapSuccess(MSK, EMSK);
+ }
+
+ @Test
+ public void testEapAkaSynchronizationFailure() {
+ verifyEapAkaIdentity();
+ verifyEapAkaSynchronizationFailure();
+ verifyEapAkaChallenge(BASE_64_RESPONSE_SUCCESS, EAP_AKA_CHALLENGE_RESPONSE);
+ verifyEapSuccess(MSK, EMSK);
+ }
+
+ @Test
+ public void testEapAkaAuthenticationReject() {
+ verifyEapAkaIdentity();
+
+ // return null from TelephonyManager to simluate rejection of AUTN
+ verifyEapAkaChallenge(null, EAP_AKA_AUTHENTICATION_REJECT);
+ verifyEapFailure();
+ }
+
+ 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(
+ 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 verifyEapAkaChallenge(String responseBase64, byte[] outgoingPacket) {
+ verifyEapAkaChallenge(
+ BASE64_CHALLENGE_1, responseBase64, EAP_AKA_CHALLENGE_REQUEST, outgoingPacket);
+ verifyNoMoreInteractions(
+ mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback);
+ }
+
+ private void verifyEapAkaChallengeWithoutIdentityReq() {
+ verifyEapAkaChallenge(
+ BASE64_CHALLENGE_1,
+ BASE_64_RESPONSE_SUCCESS,
+ EAP_AKA_CHALLENGE_REQUEST_WITHOUT_IDENTITY_REQ,
+ EAP_AKA_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 verifyEapAkaSynchronizationFailure() {
+ verifyEapAkaChallenge(
+ BASE64_CHALLENGE_2,
+ BASE_64_RESPONSE_SYNC_FAIL,
+ EAP_AKA_CHALLENGE_REQUEST_SYNC_FAIL,
+ EAP_AKA_SYNC_FAIL_RESPONSE);
+ verifyNoMoreInteractions(
+ mMockContext, mMockTelephonyManager, mMockSecureRandom, mMockCallback);
+ }
+
+ @Override
+ protected void verifyEapSuccess(byte[] msk, byte[] emsk) {
+ super.verifyEapSuccess(msk, emsk);
+
+ verifyNoMoreInteractions(mMockTelephonyManager);
+ }
+}