Loading src/java/com/android/internal/telephony/uicc/IccRecords.java +84 −59 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.os.Handler; import android.os.Message; import android.os.Registrant; import android.os.RegistrantList; import android.os.SystemClock; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.text.TextUtils; Loading Loading @@ -138,8 +139,6 @@ public abstract class IccRecords extends Handler implements IccConstants { protected boolean mIsVoiceMailFixed = false; @UnsupportedAppUsage protected String mImsi; // IMSI must be only valid numeric characters 0-9 without padding 'f's @UnsupportedAppUsage private IccIoResult auth_rsp; @UnsupportedAppUsage protected int mMncLength = UNINITIALIZED; Loading Loading @@ -174,9 +173,6 @@ public abstract class IccRecords extends Handler implements IccConstants { protected String[] mEhplmns; protected String[] mFplmns; @UnsupportedAppUsage private final Object mLock = new Object(); CarrierTestOverride mCarrierTestOverride; //Arbitrary offset for the Handler Loading Loading @@ -231,6 +227,20 @@ public abstract class IccRecords extends Handler implements IccConstants { public static final int DEFAULT_VOICE_MESSAGE_COUNT = -2; public static final int UNKNOWN_VOICE_MESSAGE_COUNT = -1; // Maximum time in millisecond to wait for a IccSim Challenge before assuming it will not // arrive and returning null to the callers. private static final long ICC_SIM_CHALLENGE_TIMEOUT_MILLIS = 2500; /** * There are two purposes for this class. First, each instance of AuthAsyncResponse acts as a * lock to for calling thead to wait in getIccSimChallengeResponse(). Second, pass the IMS * authentication response to the getIccSimChallengeResponse(). */ private static class AuthAsyncResponse { public IccIoResult authRsp; public Throwable exception; } @Override public String toString() { String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId); Loading Loading @@ -311,13 +321,6 @@ public abstract class IccRecords extends Handler implements IccConstants { public void dispose() { mDestroyed.set(true); // It is possible that there is another thread waiting for the response // to requestIccSimAuthentication() in getIccSimChallengeResponse(). auth_rsp = null; synchronized (mLock) { mLock.notifyAll(); } mCi.unregisterForIccRefresh(this); mParentApp.unregisterForReady(this); mParentApp.unregisterForLocked(this); Loading Loading @@ -890,20 +893,27 @@ public abstract class IccRecords extends Handler implements IccConstants { case EVENT_AKA_AUTHENTICATE_DONE: ar = (AsyncResult) msg.obj; auth_rsp = null; AuthAsyncResponse rsp = (AuthAsyncResponse) ar.userObj; if (DBG) log("EVENT_AKA_AUTHENTICATE_DONE"); synchronized (rsp) { if (ar.exception != null) { rsp.exception = ar.exception; loge("Exception ICC SIM AKA: " + ar.exception); } else if (ar.result == null) { rsp.exception = new NullPointerException( "Null SIM authentication response"); loge("EVENT_AKA_AUTHENTICATE_DONE: null response"); } else { try { auth_rsp = (IccIoResult)ar.result; if (DBG) log("ICC SIM AKA: auth_rsp = " + auth_rsp); } catch (Exception e) { rsp.authRsp = (IccIoResult) ar.result; if (VDBG) log("ICC SIM AKA: authRsp = " + rsp.authRsp); } catch (ClassCastException e) { rsp.exception = e; loge("Failed to parse ICC SIM AKA contents: " + e); } } synchronized (mLock) { mLock.notifyAll(); rsp.notifyAll(); } break; Loading Loading @@ -1182,54 +1192,69 @@ public abstract class IccRecords extends Handler implements IccConstants { } /** * Solve authentication leakage issue. See b/147463955. * Returns the response of the SIM application on the UICC to authentication * challenge/response algorithm. The data string and challenge response are * Base64 encoded Strings. * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102. * * @param authContext parameter P2 that specifies the authentication context per 3GPP TS 31.102 (Section 7.1.2) * @param authContext parameter P2 that specifies the authentication context * per 3GPP TS 31.102 (Section 7.1.2) * @param data authentication challenge data * @return challenge response */ @UnsupportedAppUsage @Nullable public String getIccSimChallengeResponse(int authContext, String data) { if (DBG) log("getIccSimChallengeResponse:"); if (VDBG) log("getIccSimChallengeResponse:"); //final here is for defensive copy. final CommandsInterface ci = mCi; final UiccCardApplication parentApp = mParentApp; if (ci == null || parentApp == null) { loge("getIccSimChallengeResponse: Fail, ci or parentApp is null"); return null; } AuthAsyncResponse rsp = new AuthAsyncResponse(); synchronized (rsp) { ci.requestIccSimAuthentication(authContext, data, parentApp.getAid(), obtainMessage(EVENT_AKA_AUTHENTICATE_DONE, 0, 0, rsp)); //TODO: factor wait with timeout into a separate method final long startTime = SystemClock.elapsedRealtime(); do { try { synchronized(mLock) { CommandsInterface ci = mCi; UiccCardApplication parentApp = mParentApp; if (ci != null && parentApp != null) { ci.requestIccSimAuthentication(authContext, data, parentApp.getAid(), obtainMessage(EVENT_AKA_AUTHENTICATE_DONE)); try { mLock.wait(); long sleepTime = startTime + ICC_SIM_CHALLENGE_TIMEOUT_MILLIS - SystemClock.elapsedRealtime(); if (sleepTime > 0) rsp.wait(sleepTime); } catch (InterruptedException e) { loge("getIccSimChallengeResponse: Fail, interrupted" + " while trying to request Icc Sim Auth"); return null; Rlog.w("IccRecords", "getIccSimChallengeResponse: InterruptedException."); } } else { loge( "getIccSimChallengeResponse: " + "Fail, ci or parentApp is null"); } while (SystemClock.elapsedRealtime() - startTime < ICC_SIM_CHALLENGE_TIMEOUT_MILLIS && rsp.authRsp == null && rsp.exception == null); if (SystemClock.elapsedRealtime() - startTime >= ICC_SIM_CHALLENGE_TIMEOUT_MILLIS && rsp.authRsp == null && rsp.exception == null) { loge("getIccSimChallengeResponse timeout!"); return null; } } } catch(Exception e) { loge( "getIccSimChallengeResponse: " + "Fail while trying to request Icc Sim Auth"); if (rsp.exception != null) { loge("getIccSimChallengeResponse exception: " + rsp.exception); //TODO: propagate better exceptions up to the user now that we have them available //in the call stack. return null; } if (auth_rsp == null) { if (rsp.authRsp == null) { loge("getIccSimChallengeResponse: No authentication response"); return null; } } if (VDBG) log("getIccSimChallengeResponse: return rsp.authRsp"); if (DBG) log("getIccSimChallengeResponse: return auth_rsp"); return android.util.Base64.encodeToString(auth_rsp.payload, android.util.Base64.NO_WRAP); return android.util.Base64.encodeToString(rsp.authRsp.payload, android.util.Base64.NO_WRAP); } /** Loading tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java +57 −17 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ import java.util.concurrent.atomic.AtomicInteger; public class SimulatedCommands extends BaseCommands implements CommandsInterface, SimulatedRadioControl { private final static String LOG_TAG = "SimulatedCommands"; private static final String LOG_TAG = "SimulatedCommands"; private enum SimLockState { NONE, Loading @@ -95,21 +95,27 @@ public class SimulatedCommands extends BaseCommands SIM_PERM_LOCKED } private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE; public final static String DEFAULT_SIM_PIN_CODE = "1234"; private final static String SIM_PUK_CODE = "12345678"; private final static SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE; public final static String DEFAULT_SIM_PIN2_CODE = "5678"; private final static String SIM_PUK2_CODE = "87654321"; public final static String FAKE_LONG_NAME = "Fake long name"; public final static String FAKE_SHORT_NAME = "Fake short name"; public final static String FAKE_MCC_MNC = "310260"; public final static String FAKE_IMEI = "012345678901234"; public final static String FAKE_IMEISV = "99"; public final static String FAKE_ESN = "1234"; public final static String FAKE_MEID = "1234"; public final static int DEFAULT_PIN1_ATTEMPT = 5; public final static int DEFAULT_PIN2_ATTEMPT = 5; private static final SimLockState INITIAL_LOCK_STATE = SimLockState.NONE; public static final String DEFAULT_SIM_PIN_CODE = "1234"; private static final String SIM_PUK_CODE = "12345678"; private static final SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE; public static final String DEFAULT_SIM_PIN2_CODE = "5678"; private static final String SIM_PUK2_CODE = "87654321"; public static final String FAKE_LONG_NAME = "Fake long name"; public static final String FAKE_SHORT_NAME = "Fake short name"; public static final String FAKE_MCC_MNC = "310260"; public static final String FAKE_IMEI = "012345678901234"; public static final String FAKE_IMEISV = "99"; public static final String FAKE_ESN = "1234"; public static final String FAKE_MEID = "1234"; public static final int DEFAULT_PIN1_ATTEMPT = 5; public static final int DEFAULT_PIN2_ATTEMPT = 5; public static final int ICC_AUTHENTICATION_MODE_DEFAULT = 0; public static final int ICC_AUTHENTICATION_MODE_NULL = 1; public static final int ICC_AUTHENTICATION_MODE_TIMEOUT = 2; // Maximum time in millisecond to wait for a IccSim Challenge before assuming it will not // arrive and returning null to the callers. public static final long ICC_SIM_CHALLENGE_TIMEOUT_MILLIS = 2500; private String mImei; private String mImeiSv; Loading Loading @@ -162,6 +168,8 @@ public class SimulatedCommands extends BaseCommands private SetupDataCallResult mSetupDataCallResult; private boolean mIsRadioPowerFailResponse = false; // mode for Icc Sim Authentication private int mAuthenticationMode; //***** Constructor public SimulatedCommands() { Loading @@ -179,6 +187,7 @@ public class SimulatedCommands extends BaseCommands mSimFdnEnabledState = INITIAL_FDN_STATE; mSimFdnEnabled = (mSimFdnEnabledState != SimFdnState.NONE); mPin2Code = DEFAULT_SIM_PIN2_CODE; mAuthenticationMode = ICC_AUTHENTICATION_MODE_DEFAULT; } public void dispose() { Loading Loading @@ -1896,7 +1905,38 @@ public class SimulatedCommands extends BaseCommands @Override public void requestIccSimAuthentication(int authContext, String data, String aid, Message response) { unimplemented(response); switch (mAuthenticationMode) { case ICC_AUTHENTICATION_MODE_TIMEOUT: break; case ICC_AUTHENTICATION_MODE_NULL: sendMessageResponse(response, null); break; default: if (data == null || data.length() == 0) { sendMessageResponse(response, null); } else { sendMessageResponse(response, new IccIoResult(0, 0, (byte[]) data.getBytes())); } break; } } /** * Helper function to send response msg * @param msg Response message to be sent * @param ret Return object to be included in the response message */ private void sendMessageResponse(Message msg, Object ret) { if (msg != null) { AsyncResult.forMessage(msg, ret, null); msg.sendToTarget(); } } public void setAuthenticationMode(int authenticationMode) { mAuthenticationMode = authenticationMode; } @Override Loading tests/telephonytests/src/com/android/internal/telephony/uicc/IccRecordsTest.java +94 −1 Original line number Diff line number Diff line Loading @@ -31,12 +31,14 @@ package com.android.internal.telephony.uicc; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; import android.content.Context; import android.os.AsyncResult; import android.os.HandlerThread; import android.os.Message; import android.os.SystemClock; import android.util.Log; import android.util.Pair; import com.android.internal.telephony.TelephonyTest; Loading Loading @@ -124,4 +126,95 @@ public class IccRecordsTest extends TelephonyTest { waitForLastHandlerAction(mIccRecords); assertEquals(mIccRecords.getSmsCapacityOnIcc(), 500); } @Test public void testGetIccSimChallengeResponseNull() { long startTime; long timeSpent; // EAP-SIM rand is 16 bytes. String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM="; // Test for null result mSimulatedCommands.setAuthenticationMode(mSimulatedCommands.ICC_AUTHENTICATION_MODE_NULL); startTime = SystemClock.elapsedRealtime(); assertNull("getIccAuthentication should return null for empty data.", mIccRecords.getIccSimChallengeResponse(UiccCardApplication.AUTH_CONTEXT_EAP_AKA, base64Challenge)); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); assertTrue("getIccAuthentication should not timeout", timeSpent < mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS); } @Test public void testGetIccSimChallengeResponseTimeout() { long startTime; long timeSpent; // EAP-SIM rand is 16 bytes. String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM="; mSimulatedCommands.setAuthenticationMode( mSimulatedCommands.ICC_AUTHENTICATION_MODE_TIMEOUT); startTime = SystemClock.elapsedRealtime(); assertNull("getIccAuthentication should return null for empty data.", mIccRecords.getIccSimChallengeResponse(UiccCardApplication.AUTH_CONTEXT_EAP_AKA, base64Challenge)); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); assertTrue("getIccAuthentication should timeout", timeSpent >= mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS); } @Test public void testGetIccSimChallengeResponseDefault() { long startTime; long timeSpent; // EAP-SIM rand is 16 bytes. String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM="; String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ="; // Test for default setup mSimulatedCommands.setAuthenticationMode( mSimulatedCommands.ICC_AUTHENTICATION_MODE_DEFAULT); // Test for null input startTime = SystemClock.elapsedRealtime(); assertNull("getIccAuthentication should return null for empty data.", mIccRecords.getIccSimChallengeResponse( UiccCardApplication.AUTH_CONTEXT_EAP_AKA, "")); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); assertTrue("getIccAuthentication should not timeout", timeSpent < mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS); // EAP-SIM startTime = SystemClock.elapsedRealtime(); String response = mIccRecords.getIccSimChallengeResponse( UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); Log.d("IccRecordsTest", "Result of getIccSimChallengeResponse is " + response); assertTrue("Response to EAP-SIM Challenge must not be Null.", response != null); startTime = SystemClock.elapsedRealtime(); String response1 = mIccRecords.getIccSimChallengeResponse( UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); Log.d("IccRecordsTest", "Result of getIccSimChallengeResponse is " + response1); assertTrue("Response to EAP-SIM Challenge must be consistent.", response.equals(response1)); startTime = SystemClock.elapsedRealtime(); String response2 = mIccRecords.getIccSimChallengeResponse( UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge2); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); assertTrue("Two responses must be different.", !response.equals(response2)); } } Loading
src/java/com/android/internal/telephony/uicc/IccRecords.java +84 −59 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.os.Handler; import android.os.Message; import android.os.Registrant; import android.os.RegistrantList; import android.os.SystemClock; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.text.TextUtils; Loading Loading @@ -138,8 +139,6 @@ public abstract class IccRecords extends Handler implements IccConstants { protected boolean mIsVoiceMailFixed = false; @UnsupportedAppUsage protected String mImsi; // IMSI must be only valid numeric characters 0-9 without padding 'f's @UnsupportedAppUsage private IccIoResult auth_rsp; @UnsupportedAppUsage protected int mMncLength = UNINITIALIZED; Loading Loading @@ -174,9 +173,6 @@ public abstract class IccRecords extends Handler implements IccConstants { protected String[] mEhplmns; protected String[] mFplmns; @UnsupportedAppUsage private final Object mLock = new Object(); CarrierTestOverride mCarrierTestOverride; //Arbitrary offset for the Handler Loading Loading @@ -231,6 +227,20 @@ public abstract class IccRecords extends Handler implements IccConstants { public static final int DEFAULT_VOICE_MESSAGE_COUNT = -2; public static final int UNKNOWN_VOICE_MESSAGE_COUNT = -1; // Maximum time in millisecond to wait for a IccSim Challenge before assuming it will not // arrive and returning null to the callers. private static final long ICC_SIM_CHALLENGE_TIMEOUT_MILLIS = 2500; /** * There are two purposes for this class. First, each instance of AuthAsyncResponse acts as a * lock to for calling thead to wait in getIccSimChallengeResponse(). Second, pass the IMS * authentication response to the getIccSimChallengeResponse(). */ private static class AuthAsyncResponse { public IccIoResult authRsp; public Throwable exception; } @Override public String toString() { String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId); Loading Loading @@ -311,13 +321,6 @@ public abstract class IccRecords extends Handler implements IccConstants { public void dispose() { mDestroyed.set(true); // It is possible that there is another thread waiting for the response // to requestIccSimAuthentication() in getIccSimChallengeResponse(). auth_rsp = null; synchronized (mLock) { mLock.notifyAll(); } mCi.unregisterForIccRefresh(this); mParentApp.unregisterForReady(this); mParentApp.unregisterForLocked(this); Loading Loading @@ -890,20 +893,27 @@ public abstract class IccRecords extends Handler implements IccConstants { case EVENT_AKA_AUTHENTICATE_DONE: ar = (AsyncResult) msg.obj; auth_rsp = null; AuthAsyncResponse rsp = (AuthAsyncResponse) ar.userObj; if (DBG) log("EVENT_AKA_AUTHENTICATE_DONE"); synchronized (rsp) { if (ar.exception != null) { rsp.exception = ar.exception; loge("Exception ICC SIM AKA: " + ar.exception); } else if (ar.result == null) { rsp.exception = new NullPointerException( "Null SIM authentication response"); loge("EVENT_AKA_AUTHENTICATE_DONE: null response"); } else { try { auth_rsp = (IccIoResult)ar.result; if (DBG) log("ICC SIM AKA: auth_rsp = " + auth_rsp); } catch (Exception e) { rsp.authRsp = (IccIoResult) ar.result; if (VDBG) log("ICC SIM AKA: authRsp = " + rsp.authRsp); } catch (ClassCastException e) { rsp.exception = e; loge("Failed to parse ICC SIM AKA contents: " + e); } } synchronized (mLock) { mLock.notifyAll(); rsp.notifyAll(); } break; Loading Loading @@ -1182,54 +1192,69 @@ public abstract class IccRecords extends Handler implements IccConstants { } /** * Solve authentication leakage issue. See b/147463955. * Returns the response of the SIM application on the UICC to authentication * challenge/response algorithm. The data string and challenge response are * Base64 encoded Strings. * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102. * * @param authContext parameter P2 that specifies the authentication context per 3GPP TS 31.102 (Section 7.1.2) * @param authContext parameter P2 that specifies the authentication context * per 3GPP TS 31.102 (Section 7.1.2) * @param data authentication challenge data * @return challenge response */ @UnsupportedAppUsage @Nullable public String getIccSimChallengeResponse(int authContext, String data) { if (DBG) log("getIccSimChallengeResponse:"); if (VDBG) log("getIccSimChallengeResponse:"); //final here is for defensive copy. final CommandsInterface ci = mCi; final UiccCardApplication parentApp = mParentApp; if (ci == null || parentApp == null) { loge("getIccSimChallengeResponse: Fail, ci or parentApp is null"); return null; } AuthAsyncResponse rsp = new AuthAsyncResponse(); synchronized (rsp) { ci.requestIccSimAuthentication(authContext, data, parentApp.getAid(), obtainMessage(EVENT_AKA_AUTHENTICATE_DONE, 0, 0, rsp)); //TODO: factor wait with timeout into a separate method final long startTime = SystemClock.elapsedRealtime(); do { try { synchronized(mLock) { CommandsInterface ci = mCi; UiccCardApplication parentApp = mParentApp; if (ci != null && parentApp != null) { ci.requestIccSimAuthentication(authContext, data, parentApp.getAid(), obtainMessage(EVENT_AKA_AUTHENTICATE_DONE)); try { mLock.wait(); long sleepTime = startTime + ICC_SIM_CHALLENGE_TIMEOUT_MILLIS - SystemClock.elapsedRealtime(); if (sleepTime > 0) rsp.wait(sleepTime); } catch (InterruptedException e) { loge("getIccSimChallengeResponse: Fail, interrupted" + " while trying to request Icc Sim Auth"); return null; Rlog.w("IccRecords", "getIccSimChallengeResponse: InterruptedException."); } } else { loge( "getIccSimChallengeResponse: " + "Fail, ci or parentApp is null"); } while (SystemClock.elapsedRealtime() - startTime < ICC_SIM_CHALLENGE_TIMEOUT_MILLIS && rsp.authRsp == null && rsp.exception == null); if (SystemClock.elapsedRealtime() - startTime >= ICC_SIM_CHALLENGE_TIMEOUT_MILLIS && rsp.authRsp == null && rsp.exception == null) { loge("getIccSimChallengeResponse timeout!"); return null; } } } catch(Exception e) { loge( "getIccSimChallengeResponse: " + "Fail while trying to request Icc Sim Auth"); if (rsp.exception != null) { loge("getIccSimChallengeResponse exception: " + rsp.exception); //TODO: propagate better exceptions up to the user now that we have them available //in the call stack. return null; } if (auth_rsp == null) { if (rsp.authRsp == null) { loge("getIccSimChallengeResponse: No authentication response"); return null; } } if (VDBG) log("getIccSimChallengeResponse: return rsp.authRsp"); if (DBG) log("getIccSimChallengeResponse: return auth_rsp"); return android.util.Base64.encodeToString(auth_rsp.payload, android.util.Base64.NO_WRAP); return android.util.Base64.encodeToString(rsp.authRsp.payload, android.util.Base64.NO_WRAP); } /** Loading
tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java +57 −17 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ import java.util.concurrent.atomic.AtomicInteger; public class SimulatedCommands extends BaseCommands implements CommandsInterface, SimulatedRadioControl { private final static String LOG_TAG = "SimulatedCommands"; private static final String LOG_TAG = "SimulatedCommands"; private enum SimLockState { NONE, Loading @@ -95,21 +95,27 @@ public class SimulatedCommands extends BaseCommands SIM_PERM_LOCKED } private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE; public final static String DEFAULT_SIM_PIN_CODE = "1234"; private final static String SIM_PUK_CODE = "12345678"; private final static SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE; public final static String DEFAULT_SIM_PIN2_CODE = "5678"; private final static String SIM_PUK2_CODE = "87654321"; public final static String FAKE_LONG_NAME = "Fake long name"; public final static String FAKE_SHORT_NAME = "Fake short name"; public final static String FAKE_MCC_MNC = "310260"; public final static String FAKE_IMEI = "012345678901234"; public final static String FAKE_IMEISV = "99"; public final static String FAKE_ESN = "1234"; public final static String FAKE_MEID = "1234"; public final static int DEFAULT_PIN1_ATTEMPT = 5; public final static int DEFAULT_PIN2_ATTEMPT = 5; private static final SimLockState INITIAL_LOCK_STATE = SimLockState.NONE; public static final String DEFAULT_SIM_PIN_CODE = "1234"; private static final String SIM_PUK_CODE = "12345678"; private static final SimFdnState INITIAL_FDN_STATE = SimFdnState.NONE; public static final String DEFAULT_SIM_PIN2_CODE = "5678"; private static final String SIM_PUK2_CODE = "87654321"; public static final String FAKE_LONG_NAME = "Fake long name"; public static final String FAKE_SHORT_NAME = "Fake short name"; public static final String FAKE_MCC_MNC = "310260"; public static final String FAKE_IMEI = "012345678901234"; public static final String FAKE_IMEISV = "99"; public static final String FAKE_ESN = "1234"; public static final String FAKE_MEID = "1234"; public static final int DEFAULT_PIN1_ATTEMPT = 5; public static final int DEFAULT_PIN2_ATTEMPT = 5; public static final int ICC_AUTHENTICATION_MODE_DEFAULT = 0; public static final int ICC_AUTHENTICATION_MODE_NULL = 1; public static final int ICC_AUTHENTICATION_MODE_TIMEOUT = 2; // Maximum time in millisecond to wait for a IccSim Challenge before assuming it will not // arrive and returning null to the callers. public static final long ICC_SIM_CHALLENGE_TIMEOUT_MILLIS = 2500; private String mImei; private String mImeiSv; Loading Loading @@ -162,6 +168,8 @@ public class SimulatedCommands extends BaseCommands private SetupDataCallResult mSetupDataCallResult; private boolean mIsRadioPowerFailResponse = false; // mode for Icc Sim Authentication private int mAuthenticationMode; //***** Constructor public SimulatedCommands() { Loading @@ -179,6 +187,7 @@ public class SimulatedCommands extends BaseCommands mSimFdnEnabledState = INITIAL_FDN_STATE; mSimFdnEnabled = (mSimFdnEnabledState != SimFdnState.NONE); mPin2Code = DEFAULT_SIM_PIN2_CODE; mAuthenticationMode = ICC_AUTHENTICATION_MODE_DEFAULT; } public void dispose() { Loading Loading @@ -1896,7 +1905,38 @@ public class SimulatedCommands extends BaseCommands @Override public void requestIccSimAuthentication(int authContext, String data, String aid, Message response) { unimplemented(response); switch (mAuthenticationMode) { case ICC_AUTHENTICATION_MODE_TIMEOUT: break; case ICC_AUTHENTICATION_MODE_NULL: sendMessageResponse(response, null); break; default: if (data == null || data.length() == 0) { sendMessageResponse(response, null); } else { sendMessageResponse(response, new IccIoResult(0, 0, (byte[]) data.getBytes())); } break; } } /** * Helper function to send response msg * @param msg Response message to be sent * @param ret Return object to be included in the response message */ private void sendMessageResponse(Message msg, Object ret) { if (msg != null) { AsyncResult.forMessage(msg, ret, null); msg.sendToTarget(); } } public void setAuthenticationMode(int authenticationMode) { mAuthenticationMode = authenticationMode; } @Override Loading
tests/telephonytests/src/com/android/internal/telephony/uicc/IccRecordsTest.java +94 −1 Original line number Diff line number Diff line Loading @@ -31,12 +31,14 @@ package com.android.internal.telephony.uicc; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; import android.content.Context; import android.os.AsyncResult; import android.os.HandlerThread; import android.os.Message; import android.os.SystemClock; import android.util.Log; import android.util.Pair; import com.android.internal.telephony.TelephonyTest; Loading Loading @@ -124,4 +126,95 @@ public class IccRecordsTest extends TelephonyTest { waitForLastHandlerAction(mIccRecords); assertEquals(mIccRecords.getSmsCapacityOnIcc(), 500); } @Test public void testGetIccSimChallengeResponseNull() { long startTime; long timeSpent; // EAP-SIM rand is 16 bytes. String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM="; // Test for null result mSimulatedCommands.setAuthenticationMode(mSimulatedCommands.ICC_AUTHENTICATION_MODE_NULL); startTime = SystemClock.elapsedRealtime(); assertNull("getIccAuthentication should return null for empty data.", mIccRecords.getIccSimChallengeResponse(UiccCardApplication.AUTH_CONTEXT_EAP_AKA, base64Challenge)); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); assertTrue("getIccAuthentication should not timeout", timeSpent < mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS); } @Test public void testGetIccSimChallengeResponseTimeout() { long startTime; long timeSpent; // EAP-SIM rand is 16 bytes. String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM="; mSimulatedCommands.setAuthenticationMode( mSimulatedCommands.ICC_AUTHENTICATION_MODE_TIMEOUT); startTime = SystemClock.elapsedRealtime(); assertNull("getIccAuthentication should return null for empty data.", mIccRecords.getIccSimChallengeResponse(UiccCardApplication.AUTH_CONTEXT_EAP_AKA, base64Challenge)); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); assertTrue("getIccAuthentication should timeout", timeSpent >= mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS); } @Test public void testGetIccSimChallengeResponseDefault() { long startTime; long timeSpent; // EAP-SIM rand is 16 bytes. String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM="; String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ="; // Test for default setup mSimulatedCommands.setAuthenticationMode( mSimulatedCommands.ICC_AUTHENTICATION_MODE_DEFAULT); // Test for null input startTime = SystemClock.elapsedRealtime(); assertNull("getIccAuthentication should return null for empty data.", mIccRecords.getIccSimChallengeResponse( UiccCardApplication.AUTH_CONTEXT_EAP_AKA, "")); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); assertTrue("getIccAuthentication should not timeout", timeSpent < mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS); // EAP-SIM startTime = SystemClock.elapsedRealtime(); String response = mIccRecords.getIccSimChallengeResponse( UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); Log.d("IccRecordsTest", "Result of getIccSimChallengeResponse is " + response); assertTrue("Response to EAP-SIM Challenge must not be Null.", response != null); startTime = SystemClock.elapsedRealtime(); String response1 = mIccRecords.getIccSimChallengeResponse( UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); Log.d("IccRecordsTest", "Result of getIccSimChallengeResponse is " + response1); assertTrue("Response to EAP-SIM Challenge must be consistent.", response.equals(response1)); startTime = SystemClock.elapsedRealtime(); String response2 = mIccRecords.getIccSimChallengeResponse( UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge2); timeSpent = SystemClock.elapsedRealtime() - startTime; Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent); assertTrue("Two responses must be different.", !response.equals(response2)); } }