blob: 0dc40653989d64453dfd2093ee6e281584a1bfdc [file] [log] [blame]
/*
* 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.TestUtils.hexStringToByteArray;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
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.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-SIM is functional for an end-to-end implementation
*/
public class EapSimTest {
private static final long AUTHENTICATOR_TIMEOUT_MILLIS = 250L;
private static final byte[] NONCE = hexStringToByteArray("37f3ddd3954c4831a5ee08c574844398");
private static final String UNFORMATTED_IDENTITY = "123456789ABCDEF"; // IMSI
private static final int APPTYPE_SIM = 1;
private static final int AUTHTYPE_EAP_SIM = 128;
private static final int SUB_ID = 1;
// Base 64 of: RAND
private static final String BASE64_RAND_1 = "ASNFZ4mrze8RI0VniavN7w==";
private static final String BASE64_RAND_2 = "ESNFZ4mrze8RI0VniavN7w==";
private static final String BASE64_RAND_3 = "ISNFZ4mrze8RI0VniavN7w==";
// BASE 64 of: "04" + SRES + "08" + KC
private static final String BASE64_RESP_1 = "BAq83vAI/ty6mHZUMhA=";
private static final String BASE64_RESP_2 = "BBq83vEI/ty6mHZUMhE=";
private static final String BASE64_RESP_3 = "BCq83vII/ty6mHZUMhI=";
private static final byte[] MSK = hexStringToByteArray(
"9B1E2B6892BC113F6B6D0B5789DD8ADD"
+ "B83BE2A84AA50FCAECD0003F92D8DA16"
+ "4BF983C923695C309F1D7D68DB6992B0"
+ "76EA8CE7129647A6F198F3A6AA8ADED9");
private static final byte[] EMSK = hexStringToByteArray(
"88210b6724400313539c740f417076b0"
+ "41da7e64658ec365bd2901a7cd7c2763"
+ "dad1a0508b92a42fdf85ac53c6f7e756"
+ "7f99b62bcaf467441b567f19b58d86ae");
private static final byte[] EAP_SIM_START_REQUEST = hexStringToByteArray(
"01850014120a0000" // EAP header
+ "0f02000200010000" // AT_VERSION_LIST attribute
+ "0d010000"); // AT_ANY_ID_REQ attribute
private static final byte[] EAP_SIM_START_RESPONSE = hexStringToByteArray(
"02850034120a0000" // EAP header
+ "0705000037f3ddd3954c4831a5ee08c574844398" // AT_NONCE_MT attribute
+ "10010001" // AT_SELECTED_VERSION attribute
+ "0e05001031313233343536373839414243444546"); // AT_IDENTITY attribute
private static final byte[] EAP_SIM_CHALLENGE_REQUEST = hexStringToByteArray(
"01860050120b0000" // EAP header
+ "010d0000" // AT_RAND attribute
+ "0123456789abcdef1123456789abcdef" // Rand 1
+ "1123456789abcdef1123456789abcdef" // Rand 2
+ "2123456789abcdef1123456789abcdef" // Rand 3
+ "0b050000e4675b17fa7ba4d93db48d1af9ecbb01"); // AT_MAC attribute
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;
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().setEapSimConfig(SUB_ID).build();
mEapAuthenticator =
new EapAuthenticator(
mTestLooper.getLooper(),
mMockCallback,
new EapStateMachine(mMockContext, mEapSessionConfig, mMockSecureRandom),
(runnable) -> runnable.run(),
AUTHENTICATOR_TIMEOUT_MILLIS);
}
@Test
public void testEapSimEndToEnd() {
// EAP-SIM/Start request
when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE))
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.createForSubscriptionId(SUB_ID))
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.getSubscriberId()).thenReturn(UNFORMATTED_IDENTITY);
doAnswer(invocation -> {
byte[] dst = invocation.getArgument(0);
System.arraycopy(NONCE, 0, dst, 0, NONCE.length);
return null;
}).when(mMockSecureRandom).nextBytes(eq(new byte[NONCE.length]));
mEapAuthenticator.processEapMessage(EAP_SIM_START_REQUEST);
mTestLooper.dispatchAll();
verify(mMockContext).getSystemService(eq(Context.TELEPHONY_SERVICE));
verify(mMockTelephonyManager).createForSubscriptionId(SUB_ID);
verify(mMockTelephonyManager).getSubscriberId();
verify(mMockSecureRandom).nextBytes(any(byte[].class));
// verify EAP-SIM/Start response
verify(mMockCallback).onResponse(eq(EAP_SIM_START_RESPONSE));
verifyNoMoreInteractions(
mMockContext,
mMockTelephonyManager,
mMockSecureRandom,
mMockCallback);
// EAP-SIM/Challenge request
when(mMockTelephonyManager
.getIccAuthentication(APPTYPE_SIM, AUTHTYPE_EAP_SIM, BASE64_RAND_1))
.thenReturn(BASE64_RESP_1);
when(mMockTelephonyManager
.getIccAuthentication(APPTYPE_SIM, AUTHTYPE_EAP_SIM, BASE64_RAND_2))
.thenReturn(BASE64_RESP_2);
when(mMockTelephonyManager
.getIccAuthentication(APPTYPE_SIM, AUTHTYPE_EAP_SIM, BASE64_RAND_3))
.thenReturn(BASE64_RESP_3);
mEapAuthenticator.processEapMessage(EAP_SIM_CHALLENGE_REQUEST);
mTestLooper.dispatchAll();
// verify EAP-SIM/Challenge response
verify(mMockTelephonyManager)
.getIccAuthentication(eq(APPTYPE_SIM), eq(AUTHTYPE_EAP_SIM), eq(BASE64_RAND_1));
verify(mMockTelephonyManager)
.getIccAuthentication(eq(APPTYPE_SIM), eq(AUTHTYPE_EAP_SIM), eq(BASE64_RAND_2));
verify(mMockTelephonyManager)
.getIccAuthentication(eq(APPTYPE_SIM), eq(AUTHTYPE_EAP_SIM), eq(BASE64_RAND_3));
verify(mMockCallback).onResponse(eq(EAP_SIM_CHALLENGE_RESPONSE));
verifyNoMoreInteractions(
mMockContext,
mMockTelephonyManager,
mMockSecureRandom,
mMockCallback);
// 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);
}
}