• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.uicc;
18 
19 import static android.security.keystore.KeyProperties.AUTH_DEVICE_CREDENTIAL;
20 import static android.security.keystore.KeyProperties.BLOCK_MODE_GCM;
21 import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_NONE;
22 import static android.security.keystore.KeyProperties.KEY_ALGORITHM_AES;
23 import static android.security.keystore.KeyProperties.PURPOSE_DECRYPT;
24 import static android.security.keystore.KeyProperties.PURPOSE_ENCRYPT;
25 
26 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT;
27 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__CACHED_PIN_DISCARDED;
28 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_COUNT_NOT_MATCHING_AFTER_REBOOT;
29 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_DECRYPTION_ERROR;
30 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_ENCRYPTION_ERROR;
31 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_ENCRYPTION_KEY_MISSING;
32 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_REQUIRED_AFTER_REBOOT;
33 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_STORED_FOR_VERIFICATION;
34 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_FAILURE;
35 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SKIPPED_SIM_CARD_MISMATCH;
36 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SUCCESS;
37 import static com.android.internal.telephony.uicc.IccCardStatus.PinState.PINSTATE_ENABLED_NOT_VERIFIED;
38 import static com.android.internal.telephony.uicc.IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED;
39 import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING;
40 
41 import android.annotation.Nullable;
42 import android.app.KeyguardManager;
43 import android.content.BroadcastReceiver;
44 import android.content.Context;
45 import android.content.Intent;
46 import android.content.IntentFilter;
47 import android.content.SharedPreferences;
48 import android.os.AsyncResult;
49 import android.os.Handler;
50 import android.os.Message;
51 import android.os.PersistableBundle;
52 import android.os.WorkSource;
53 import android.provider.Settings;
54 import android.security.keystore.KeyGenParameterSpec;
55 import android.telephony.CarrierConfigManager;
56 import android.telephony.TelephonyManager;
57 import android.telephony.TelephonyManager.SimState;
58 import android.util.Base64;
59 import android.util.IndentingPrintWriter;
60 import android.util.Log;
61 import android.util.SparseArray;
62 
63 import com.android.internal.R;
64 import com.android.internal.annotations.VisibleForTesting;
65 import com.android.internal.telephony.Phone;
66 import com.android.internal.telephony.PhoneConstants;
67 import com.android.internal.telephony.PhoneFactory;
68 import com.android.internal.telephony.TelephonyStatsLog;
69 import com.android.internal.telephony.nano.StoredPinProto.EncryptedPin;
70 import com.android.internal.telephony.nano.StoredPinProto.StoredPin;
71 import com.android.internal.telephony.nano.StoredPinProto.StoredPin.PinStatus;
72 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
73 import com.android.internal.util.ArrayUtils;
74 import com.android.telephony.Rlog;
75 
76 import java.io.FileDescriptor;
77 import java.io.PrintWriter;
78 import java.security.KeyStore;
79 import java.util.Arrays;
80 import java.util.Calendar;
81 import java.util.Date;
82 
83 import javax.crypto.Cipher;
84 import javax.crypto.KeyGenerator;
85 import javax.crypto.SecretKey;
86 import javax.crypto.spec.GCMParameterSpec;
87 
88 /**
89  * This class stores the SIM PIN for automatic verification after an unattended reboot.
90  */
91 public class PinStorage extends Handler {
92     private static final String TAG = "PinStorage";
93     private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
94             Rlog.isLoggable(TAG, Log.VERBOSE);
95 
96     /**
97      * Time duration in milliseconds to allow automatic PIN verification after reboot. All unused
98      * PINs are discarded when the timer expires.
99      */
100     private static final int TIMER_VALUE_AFTER_OTA_MILLIS = 20_000;
101 
102     /**
103      * Time duration in milliseconds to reboot the device after {@code prepareUnattendedReboot}
104      * is invoked. After the time expires, a new invocation of {@code prepareUnattendedReboot} is
105      * required to perform the automatic PIN verification after reboot.
106      */
107     private static final int TIMER_VALUE_BEFORE_OTA_MILLIS = 20_000;
108 
109     /** Minimum valid length of the ICCID. */
110     private static final int MIN_ICCID_LENGTH = 12;
111     /** Minimum length of the SIM PIN, as per 3GPP TS 31.101. */
112     private static final int MIN_PIN_LENGTH = 4;
113     /** Maximum length of the SIM PIN, as per 3GPP TS 31.101. */
114     private static final int MAX_PIN_LENGTH = 8;
115 
116     // Variables related to the encryption of the SIM PIN.
117     private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore";
118     private static final String CIPHER_TRANSFORMATION = "AES/GCM/NoPadding";
119     private static final int GCM_PARAMETER_TAG_BIT_LEN = 128;
120     private static final int SHORT_TERM_KEY_DURATION_MINUTES = 15;
121 
122     /** Alias of the long-term key that does not require user authentication. */
123     private static final String KEYSTORE_ALIAS_LONG_TERM_ALWAYS = "PinStorage_longTerm_always_key";
124     /** Alias of the user authentication blound long-term key. */
125     private static final String KEYSTORE_ALIAS_LONG_TERM_USER_AUTH = "PinStorage_longTerm_ua_key";
126     /** Alias of the short-term key (30 minutes) used before and after an unattended reboot. */
127     private static final String KEYSTORE_ALIAS_SHORT_TERM = "PinStorage_shortTerm_key";
128 
129     // Constants related to the storage of the encrypted SIM PIN to non-volatile memory.
130     // Data is stored in two separate files:
131     //  - "available" is for the PIN(s) in AVAILABLE state and uses a key that does not expire
132     //  - "reboot" is for the PIN(s) in other states and uses a short-term key (30 minutes)
133     private static final String SHARED_PREFS_NAME = "pinstorage_prefs";
134     private static final String SHARED_PREFS_AVAILABLE_PIN_BASE_KEY = "encrypted_pin_available_";
135     private static final String SHARED_PREFS_REBOOT_PIN_BASE_KEY = "encrypted_pin_reboot_";
136     private static final String SHARED_PREFS_STORED_PINS = "stored_pins";
137 
138     // Events
139     private static final int ICC_CHANGED_EVENT = 1;
140     private static final int TIMER_EXPIRATION_EVENT = 3;
141     private static final int USER_UNLOCKED_EVENT = 4;
142     private static final int SUPPLY_PIN_COMPLETE = 5;
143 
144     private final Context mContext;
145     private final int mBootCount;
146     private final KeyStore mKeyStore;
147 
148     private SecretKey mLongTermSecretKey;
149     private SecretKey mShortTermSecretKey;
150 
151     private boolean mIsDeviceSecure;
152     private boolean mIsDeviceLocked;
153     private boolean mLastCommitResult = true;
154 
155     /** Duration of the short-term key, in minutes. */
156     @VisibleForTesting
157     public int mShortTermSecretKeyDurationMinutes;
158 
159     /** RAM storage is used on secure devices before the device is unlocked. */
160     private final SparseArray<byte[]> mRamStorage;
161 
162     /** Receiver for the required intents. */
163     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
164         @Override
165         public void onReceive(Context context, Intent intent) {
166             String action = intent.getAction();
167             if (TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED.equals(action)
168                     || TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED.equals(action)) {
169                 int slotId = intent.getIntExtra(PhoneConstants.PHONE_KEY, -1);
170                 int state = intent.getIntExtra(
171                         TelephonyManager.EXTRA_SIM_STATE, TelephonyManager.SIM_STATE_UNKNOWN);
172                 if (validateSlotId(slotId)) {
173                     sendMessage(obtainMessage(ICC_CHANGED_EVENT, slotId, state));
174                 }
175             } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
176                 sendMessage(obtainMessage(USER_UNLOCKED_EVENT));
177             }
178         }
179     };
180 
PinStorage(Context context)181     public PinStorage(Context context) {
182         mContext = context;
183         mBootCount = getBootCount();
184         mKeyStore = initializeKeyStore();
185         mShortTermSecretKeyDurationMinutes = SHORT_TERM_KEY_DURATION_MINUTES;
186 
187         mIsDeviceSecure = isDeviceSecure();
188         mIsDeviceLocked = mIsDeviceSecure ? isDeviceLocked() : false;
189 
190         // Register for necessary intents.
191         IntentFilter intentFilter = new IntentFilter();
192         intentFilter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
193         intentFilter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
194         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
195         mContext.registerReceiver(mBroadcastReceiver, intentFilter);
196 
197         CarrierConfigManager ccm = mContext.getSystemService(CarrierConfigManager.class);
198         // Callback directly handle config change and should be executed in handler thread
199         if (ccm != null) {
200             ccm.registerCarrierConfigChangeListener(this::post,
201                     (slotIndex, subId, carrierId, specificCarrierId) ->
202                             onCarrierConfigurationChanged(slotIndex));
203         }
204 
205         // Initialize the long term secret key. This needs to be present in all cases:
206         //  - if the device is not secure or is locked: key does not require user authentication
207         //  - if the device is secure and unlocked: key requires user authentication.
208         // The short term key is retrieved later when needed.
209         String alias = (!mIsDeviceSecure || mIsDeviceLocked)
210                 ? KEYSTORE_ALIAS_LONG_TERM_ALWAYS : KEYSTORE_ALIAS_LONG_TERM_USER_AUTH;
211         mLongTermSecretKey = initializeSecretKey(alias, /*createIfAbsent=*/ true);
212 
213         // If the device is not securee or is unlocked, we can start logic. Otherwise we need to
214         // wait for the device to be unlocked and store any temporary PIN in RAM.
215         if (!mIsDeviceSecure || !mIsDeviceLocked) {
216             mRamStorage = null;
217             onDeviceReady();
218         } else {
219             logd("Device is locked - Postponing initialization");
220             mRamStorage = new SparseArray<>();
221         }
222     }
223 
224     /** Store the {@code pin} for the {@code slotId}. */
storePin(String pin, int slotId)225     public synchronized void storePin(String pin, int slotId) {
226         String iccid = getIccid(slotId);
227 
228         if (!validatePin(pin) || !validateIccid(iccid) || !validateSlotId(slotId)) {
229             // We are unable to store the PIN. At least clear the old one, if present.
230             loge("storePin[%d] - Invalid PIN, slotId or ICCID", slotId);
231             clearPin(slotId);
232             return;
233         }
234         if (!isCacheAllowed(slotId)) {
235             logd("storePin[%d]: caching it not allowed", slotId);
236             return;
237         }
238 
239         logd("storePin[%d]", slotId);
240 
241         StoredPin storedPin = new StoredPin();
242         storedPin.iccid = iccid;
243         storedPin.pin = pin;
244         storedPin.slotId = slotId;
245         storedPin.status = PinStatus.AVAILABLE;
246 
247         savePinInformation(slotId, storedPin);
248     }
249 
250     /** Clear the cached pin for the {@code slotId}. */
clearPin(int slotId)251     public synchronized void clearPin(int slotId) {
252         logd("clearPin[%d]", slotId);
253 
254         if (!validateSlotId(slotId)) {
255             return;
256         }
257         savePinInformation(slotId, null);
258     }
259 
260     /**
261      * Return the cached pin for the SIM card identified by {@code slotId} and {@code iccid}, or
262      * an empty string if it is not available.
263      *
264      * The method returns the PIN only if the state is VERIFICATION_READY. If the PIN is found,
265      * its state changes to AVAILABLE, so that it cannot be retrieved a second time during the
266      * same boot cycle. If the PIN verification fails, it will be removed after the failed attempt.
267      */
getPin(int slotId, String iccid)268     public synchronized String getPin(int slotId, String iccid) {
269         if (!validateSlotId(slotId) || !validateIccid(iccid)) {
270             return "";
271         }
272 
273         StoredPin storedPin = loadPinInformation(slotId);
274         if (storedPin != null) {
275             if (!storedPin.iccid.equals(iccid)) {
276                 // The ICCID does not match: it's possible that the SIM card was changed.
277                 // Delete the cached PIN.
278                 savePinInformation(slotId, null);
279                 TelephonyStatsLog.write(PIN_STORAGE_EVENT,
280                         PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SKIPPED_SIM_CARD_MISMATCH,
281                         /* number_of_pins= */ 1, /* package_name= */ "");
282             } else if (storedPin.status == PinStatus.VERIFICATION_READY) {
283                 logd("getPin[%d] - Found PIN ready for verification", slotId);
284                 // Move the state to AVAILABLE, so that it cannot be retrieved again.
285                 storedPin.status = PinStatus.AVAILABLE;
286                 savePinInformation(slotId, storedPin);
287                 return storedPin.pin;
288             }
289         }
290         return "";
291     }
292 
293     /**
294      * Prepare for an unattended reboot.
295      *
296      * All PINs in AVAILABLE and VERIFICATION_READY state are moved to REBOOT_READY state. A
297      * timer is started to make sure that reboot occurs shortly after invoking this method.
298      *
299      * @return The result of the reboot preparation.
300      */
301     @TelephonyManager.PrepareUnattendedRebootResult
prepareUnattendedReboot(WorkSource workSource)302     public synchronized int prepareUnattendedReboot(WorkSource workSource) {
303         // Unattended reboot should never occur before the device is unlocked.
304         if (mIsDeviceLocked) {
305             loge("prepareUnattendedReboot - Device is locked");
306             return TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR;
307         }
308 
309         // Start timer to make sure that device is rebooted shortly after this is executed.
310         if (!startTimer(TIMER_VALUE_BEFORE_OTA_MILLIS)) {
311             return TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR;
312         }
313 
314         int numSlots = getSlotCount();
315         SparseArray<StoredPin> storedPins = loadPinInformation();
316 
317         // Delete any previous short-term key, if present: a new one is created (if needed).
318         deleteSecretKey(KEYSTORE_ALIAS_SHORT_TERM);
319         mShortTermSecretKey = null;
320 
321         // If any PIN is present, generate a new short-term key to save PIN(s) to
322         // non-volatile memory.
323         if (storedPins.size() > 0) {
324             mShortTermSecretKey =
325                     initializeSecretKey(KEYSTORE_ALIAS_SHORT_TERM, /*createIfAbsent=*/ true);
326         }
327 
328         @TelephonyManager.PrepareUnattendedRebootResult
329         int result =  TelephonyManager.PREPARE_UNATTENDED_REBOOT_SUCCESS;
330         int storedCount = 0;
331         int notAvailableCount = 0;
332 
333         for (int slotId = 0; slotId < numSlots; slotId++) {
334             StoredPin storedPin = storedPins.get(slotId);
335             if (storedPin != null) {
336                 storedPin.status = PinStatus.REBOOT_READY;
337                 if (!savePinInformation(slotId, storedPin)) {
338                     result = TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR;
339                     break;
340                 }
341                 storedCount++;
342             } else if (isPinState(slotId, PINSTATE_ENABLED_VERIFIED)) {
343                 // If PIN is not available, check if PIN will be required after reboot (current PIN
344                 // status is enabled and verified).
345                 loge("Slot %d requires PIN and is not cached", slotId);
346                 result = TelephonyManager.PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED;
347                 notAvailableCount++;
348             }
349         }
350 
351         // Generate metrics
352         String callingPackage = workSource == null || workSource.size() == 0
353                                     ? "" : workSource.getPackageName(0);
354         if (result == TelephonyManager.PREPARE_UNATTENDED_REBOOT_SUCCESS) {
355             logd("prepareUnattendedReboot - Stored %d PINs", storedCount);
356             TelephonyStatsLog.write(PIN_STORAGE_EVENT,
357                     PIN_STORAGE_EVENT__EVENT__PIN_STORED_FOR_VERIFICATION, storedCount,
358                     callingPackage);
359         } else if (result == TelephonyManager.PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED) {
360             logd("prepareUnattendedReboot - Required %d PINs after reboot", notAvailableCount);
361             TelephonyStatsLog.write(PIN_STORAGE_EVENT,
362                     PIN_STORAGE_EVENT__EVENT__PIN_REQUIRED_AFTER_REBOOT, notAvailableCount,
363                     callingPackage);
364         }
365 
366         // Save number of PINs to generate metrics after reboot
367         saveNumberOfCachedPins(storedCount);
368 
369         return result;
370     }
371 
372     /**
373      * Execute logic when a secure device is unlocked.
374      *
375      * The temporary long-term key that does not require user verification is replaced by the long
376      * term key that requires user verification. The cached PIN temporarily stored in RAM are
377      * merged with those on disk from the previous boot.
378      */
onUserUnlocked()379     private synchronized void onUserUnlocked() {
380         if (!mIsDeviceLocked) {
381             // This should never happen.
382             // Nothing to do because the device was already unlocked before
383             return;
384         }
385 
386         logd("onUserUnlocked - Device is unlocked");
387 
388         // It's possible that SIM PIN was already verified and stored temporarily in RAM. Load the
389         // data and erase the memory.
390         SparseArray<StoredPin> storedPinInRam = loadPinInformation();
391         cleanRamStorage();
392 
393         // Mark the device as unlocked
394         mIsDeviceLocked = false;
395 
396         // Replace the temporary long-term key without user authentication with a new long-term
397         // key that requires user authentication to save all PINs previously in RAM (all in
398         // AVAILABLE state) to disk.
399         mLongTermSecretKey =
400                 initializeSecretKey(KEYSTORE_ALIAS_LONG_TERM_USER_AUTH, /*createIfAbsent=*/ true);
401 
402         // Save the PINs previously in RAM to disk, overwriting any PIN that might already exists.
403         for (int i = 0; i < storedPinInRam.size(); i++) {
404             savePinInformation(storedPinInRam.keyAt(i), storedPinInRam.valueAt(i));
405         }
406 
407         // At this point the module is fully initialized. Execute the start logic.
408         onDeviceReady();
409 
410         // Verify any pending PIN for SIM cards that need it.
411         verifyPendingPins();
412     }
413 
414     /**
415      * Executes logic when module is fully ready. This occurs immediately if the device is not
416      * secure or after the user unlocks the device.
417      *
418      * At this point, the short-term key is initialized (if present), the configuration is read
419      * and the status of each PIN is updated as needed.
420      */
onDeviceReady()421     private void onDeviceReady() {
422         logd("onDeviceReady");
423 
424         // Try to initialize the short term key, if present, as this would be required to read
425         // stored PIN for verification.
426         mShortTermSecretKey =
427                 initializeSecretKey(KEYSTORE_ALIAS_SHORT_TERM, /*createIfAbsent=*/ false);
428 
429         int verificationReadyCount = 0;
430         int slotCount = getSlotCount();
431         for (int slotId = 0; slotId < slotCount; slotId++) {
432             // Read PIN information from storage
433             StoredPin storedPin = loadPinInformation(slotId);
434             if (storedPin == null) {
435                 continue;
436             }
437 
438             // For each PIN in AVAILABLE state, check the boot count.
439             // If the boot count matches, it means that module crashed and it's ok to preserve
440             // the PIN code. If the boot count does not match, then delete those PINs.
441             if (storedPin.status == PinStatus.AVAILABLE) {
442                 if (storedPin.bootCount != mBootCount) {
443                     logd("Boot count [%d] does not match - remove PIN", slotId);
444                     savePinInformation(slotId, null);
445                     continue;
446                 }
447                 logd("Boot count [%d] matches - keep stored PIN", slotId);
448             }
449 
450             // If there is any PIN in REBOOT_READY state, move it to VERIFICATION_READY and start
451             // the timer. Don't change PINs that might be already in VERIFICATION_READY state
452             // (e.g. due to crash).
453             if (storedPin.status == PinStatus.REBOOT_READY) {
454                 storedPin.status = PinStatus.VERIFICATION_READY;
455                 savePinInformation(slotId, storedPin);
456                 verificationReadyCount++;
457             }
458         }
459         if (verificationReadyCount > 0) {
460             startTimer(TIMER_VALUE_AFTER_OTA_MILLIS);
461         }
462 
463         // Generate metrics for PINs that had been stored before reboot, but are not available
464         // after. This can happen if there is an excessive delay in unlocking the device (short
465         // term key expires), but also if a new SIM card without PIN is present.
466         int prevCachedPinCount = saveNumberOfCachedPins(0);
467         if (prevCachedPinCount > verificationReadyCount) {
468             TelephonyStatsLog.write(PIN_STORAGE_EVENT,
469                     PIN_STORAGE_EVENT__EVENT__PIN_COUNT_NOT_MATCHING_AFTER_REBOOT,
470                     prevCachedPinCount - verificationReadyCount, /* package_name= */ "");
471         }
472     }
473 
474     /**
475      * Executes logic at the expiration of the timer. This method is common for two cases:
476      *  - timer started after unattended reeboot to verify the SIM PIN automatically
477      *  - timer started after prepareUnattendedReboot() is invoked.
478      */
onTimerExpiration()479     private synchronized void onTimerExpiration() {
480         logd("onTimerExpiration");
481 
482         int discardedPin = 0;
483         int slotCount = getSlotCount();
484         for (int slotId = 0; slotId < slotCount; slotId++) {
485             // Read PIN information from storage
486             StoredPin storedPin = loadPinInformation(slotId);
487             if (storedPin == null) {
488                 continue;
489             }
490 
491             // Delete all PINs in VERIFICATION_READY state. This happens when reboot occurred after
492             // OTA, but the SIM card is not detected on the device.
493             if (storedPin.status == PinStatus.VERIFICATION_READY) {
494                 logd("onTimerExpiration - Discarding PIN in slot %d", slotId);
495                 savePinInformation(slotId, null);
496                 discardedPin++;
497                 continue;
498             }
499 
500             // Move all PINs in REBOOT_READY to AVAILABLE. This happens when
501             // prepareUnattendedReboot() is invoked, but the reboot does not occur.
502             if (storedPin.status == PinStatus.REBOOT_READY) {
503                 logd("onTimerExpiration - Moving PIN in slot %d back to AVAILABLE", slotId);
504                 storedPin.status = PinStatus.AVAILABLE;
505                 savePinInformation(slotId, storedPin);
506                 continue;
507             }
508         }
509 
510         // Delete short term key no matter the reason of the timer expiration.
511         // This is done after loading the PIN information, so that it's possible to change
512         // the status of the PIN as needed.
513         deleteSecretKey(KEYSTORE_ALIAS_SHORT_TERM);
514         mShortTermSecretKey = null;
515 
516         // Reset number of stored PINs (applicable if timer expired before unattended reboot).
517         saveNumberOfCachedPins(0);
518 
519         // Write metrics about number of discarded PINs
520         if (discardedPin > 0) {
521             TelephonyStatsLog.write(PIN_STORAGE_EVENT,
522                     PIN_STORAGE_EVENT__EVENT__CACHED_PIN_DISCARDED, discardedPin,
523                     /* package_name= */ "");
524         }
525     }
526 
527     /** Handle the update of the {@code state} of the SIM card in {@code slotId}. */
onSimStatusChange(int slotId, @SimState int state)528     private synchronized void onSimStatusChange(int slotId, @SimState int state) {
529         logd("SIM card/application changed[%d]: %s", slotId,
530                 TelephonyManager.simStateToString(state));
531         switch (state) {
532             case TelephonyManager.SIM_STATE_ABSENT:
533             case TelephonyManager.SIM_STATE_PIN_REQUIRED: {
534                 // These states are likely to occur after a reboot, so we don't clear cached PINs
535                 // in VERIFICATION_READY state, as they might be verified later, when the SIM is
536                 // detected. On the other hand, we remove PINs in AVAILABLE state.
537                 StoredPin storedPin = loadPinInformation(slotId);
538                 if (storedPin != null && storedPin.status != PinStatus.VERIFICATION_READY) {
539                     savePinInformation(slotId, null);
540                 }
541                 break;
542             }
543             case TelephonyManager.SIM_STATE_PUK_REQUIRED:
544             case TelephonyManager.SIM_STATE_PERM_DISABLED:
545             case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
546                 // These states indicate that the SIM card will need a manual PIN verification.
547                 // Delete the cached PIN regardless of its state.
548                 clearPin(slotId);
549                 break;
550             case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
551             case TelephonyManager.SIM_STATE_CARD_RESTRICTED:
552             case TelephonyManager.SIM_STATE_LOADED:
553             case TelephonyManager.SIM_STATE_READY: {
554                 // These states can occur after successful PIN caching, so we don't clear cached
555                 // PINs in AVAILABLE state, as they need to be retained. We clear any PIN in
556                 // other states, as they are no longer needed for automatic verification.
557                 StoredPin storedPin = loadPinInformation(slotId);
558                 if (storedPin != null && storedPin.status != PinStatus.AVAILABLE) {
559                     savePinInformation(slotId, null);
560                 }
561                 break;
562             }
563 
564             case TelephonyManager.SIM_STATE_NOT_READY:
565             case TelephonyManager.SIM_STATE_PRESENT:
566             default:
567                 break;
568         }
569     }
570 
onCarrierConfigurationChanged(int slotId)571     private void onCarrierConfigurationChanged(int slotId) {
572         logv("onCarrierConfigChanged[%d]", slotId);
573         if (!isCacheAllowed(slotId)) {
574             logd("onCarrierConfigChanged[%d] - PIN caching not allowed", slotId);
575             clearPin(slotId);
576         }
577     }
578 
onSupplyPinComplete(int slotId, boolean success)579     private void onSupplyPinComplete(int slotId, boolean success) {
580         logd("onSupplyPinComplete[%d] - success: %s", slotId, success);
581         if (!success) {
582             // In case of failure to verify the PIN, delete the stored value.
583             // Otherwise nothing to do.
584             clearPin(slotId);
585         }
586         // Update metrics:
587         TelephonyStatsLog.write(
588                 PIN_STORAGE_EVENT,
589                 success
590                     ? PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SUCCESS
591                     : PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_FAILURE,
592                 /* number_of_pins= */ 1, /* package_name= */ "");
593     }
594 
595     @Override
handleMessage(Message msg)596     public void handleMessage(Message msg) {
597         switch (msg.what) {
598             case ICC_CHANGED_EVENT:
599                 onSimStatusChange(/* slotId= */ msg.arg1, /* state= */ msg.arg2);
600                 break;
601             case TIMER_EXPIRATION_EVENT:
602                 onTimerExpiration();
603                 break;
604             case USER_UNLOCKED_EVENT:
605                 onUserUnlocked();
606                 break;
607             case SUPPLY_PIN_COMPLETE:
608                 AsyncResult ar = (AsyncResult) msg.obj;
609                 boolean success = ar != null && ar.exception == null;
610                 onSupplyPinComplete(/* slotId= */ msg.arg2, success);
611                 break;
612             default:
613                 // Nothing to do
614                 break;
615         }
616     }
617 
618     /** Return if the device is secure (device PIN is enabled). */
isDeviceSecure()619     private boolean isDeviceSecure() {
620         KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
621         return keyguardManager != null ? keyguardManager.isDeviceSecure() : false;
622     }
623 
624     /** Return if the device is locked (device PIN is enabled and not verified). */
isDeviceLocked()625     private boolean isDeviceLocked() {
626         KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
627         return keyguardManager != null
628                 ? keyguardManager.isDeviceSecure() && keyguardManager.isDeviceLocked()
629                 : false;
630     }
631 
632     /** Loads the stored PIN informations for all SIM slots. */
loadPinInformation()633     private SparseArray<StoredPin> loadPinInformation() {
634         SparseArray<StoredPin> result = new SparseArray<>();
635         int slotCount = getSlotCount();
636         for (int slotId = 0; slotId < slotCount; slotId++) {
637             StoredPin storedPin = loadPinInformation(slotId);
638             if (storedPin != null) {
639                 result.put(slotId, storedPin);
640             }
641         }
642         return result;
643     }
644 
645     /**
646      * Loads the stored PIN information for the {@code slotId}.
647      *
648      * The RAM storage is used if the device is locked, the disk storage is used otherwise.
649      * This method tries to use both the long-term key and the short-term key (if available)
650      * to retrieve the PIN information, regardless of its status.
651      *
652      * @return the stored {@code StoredPin}, or null if not present.
653      */
654     @Nullable
loadPinInformation(int slotId)655     private StoredPin loadPinInformation(int slotId) {
656         if (!mLastCommitResult) {
657             // If the last commit failed, do not read from file, as we might retrieve stale data.
658             loge("Last commit failed - returning empty values");
659             return null;
660         }
661 
662         StoredPin result = null;
663 
664         if (mIsDeviceLocked) {
665             // If the device is still locked, retrieve data from RAM storage.
666             if (mRamStorage != null && mRamStorage.get(slotId) != null) {
667                 result =  decryptStoredPin(mRamStorage.get(slotId), mLongTermSecretKey);
668             }
669         } else {
670             // Load both the stored PIN in available state (with long-term key) and in other states
671             // (with short-term key). At most one of them should be present at any given time and
672             // we treat the case wheere both are present as an error.
673             StoredPin availableStoredPin = loadPinInformationFromDisk(
674                     slotId, SHARED_PREFS_AVAILABLE_PIN_BASE_KEY, mLongTermSecretKey);
675             StoredPin rebootStoredPin = loadPinInformationFromDisk(
676                     slotId, SHARED_PREFS_REBOOT_PIN_BASE_KEY, mShortTermSecretKey);
677             if (availableStoredPin != null && rebootStoredPin == null) {
678                 result = availableStoredPin;
679             } else if (availableStoredPin == null && rebootStoredPin != null) {
680                 result = rebootStoredPin;
681             }
682         }
683 
684         // Validate the slot ID of the retrieved PIN information
685         if (result != null && result.slotId != slotId) {
686             loge("Load PIN: slot ID does not match (%d != %d)", result.slotId, slotId);
687             result = null;
688         }
689 
690         if (result != null) {
691             logv("Load PIN: %s", result.toString());
692         } else {
693             logv("Load PIN for slot %d: null", slotId);
694         }
695         return result;
696     }
697 
698     /**
699      * Load the PIN information from a specific file in non-volatile memory.
700      *
701      * @param key the key in the {@code SharedPreferences} to read
702      * @param secretKey the key used for encryption/decryption
703      * @return the {@code StoredPin} from non-volatile memory. It returns a default instance in
704      * case of error.
705      */
706     @Nullable
loadPinInformationFromDisk( int slotId, String key, @Nullable SecretKey secretKey)707     private StoredPin loadPinInformationFromDisk(
708             int slotId, String key, @Nullable SecretKey secretKey) {
709         String base64encryptedPin =
710                 mContext.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
711                     .getString(key + slotId, "");
712         if (!base64encryptedPin.isEmpty()) {
713             try {
714                 byte[] blob = Base64.decode(base64encryptedPin, Base64.DEFAULT);
715                 return decryptStoredPin(blob, secretKey);
716             } catch (Exception e) {
717                 // Nothing to do
718             }
719         }
720         return null;
721     }
722 
723     /** Load the PIN information from an encrypted binary blob.
724      *
725      * @param blob the encrypted binary blob
726      * @param secretKey the key used for encryption/decryption
727      * @return the decrypted {@code StoredPin}, or null in case of error.
728      */
729     @Nullable
decryptStoredPin(byte[] blob, @Nullable SecretKey secretKey)730     private StoredPin decryptStoredPin(byte[] blob, @Nullable SecretKey secretKey) {
731         if (secretKey == null) {
732             TelephonyStatsLog.write(PIN_STORAGE_EVENT,
733                     PIN_STORAGE_EVENT__EVENT__PIN_ENCRYPTION_KEY_MISSING,
734                     /* number_of_pins= */ 1, /* package_name= */ "");
735         } else {
736             try {
737                 byte[] decryptedPin = decrypt(secretKey, blob);
738                 if (decryptedPin.length > 0) {
739                     return StoredPin.parseFrom(decryptedPin);
740                 }
741             } catch (Exception e) {
742                 loge("cannot decrypt/parse PIN information", e);
743             }
744         }
745         return null;
746     }
747 
748     /**
749      * Stores the PIN information.
750      *
751      * If the device is locked, the PIN information is stored to RAM, othewrwise to disk.
752      * The PIN information is divided based on the PIN status and stored in two separate
753      * files in non-volatile memory, each encrypted with a different key.
754      *
755      * @param slotId the slot ID
756      * @param storedPin the PIN information to be stored
757      * @return true if the operation was successfully done, false otherwise.
758      */
savePinInformation(int slotId, @Nullable StoredPin storedPin)759     private boolean savePinInformation(int slotId, @Nullable StoredPin storedPin) {
760         // Populate the boot count
761         if (storedPin != null) {
762             storedPin.bootCount = mBootCount;
763         }
764 
765         // If the device is still locked, we can only save PINs in AVAILABLE state in RAM.
766         // NOTE: at this point, there should not be any PIN in any other state.
767         if (mIsDeviceLocked) {
768             return savePinInformationToRam(slotId, storedPin);
769         }
770 
771         // Remove any prvious key related to this slot.
772         SharedPreferences.Editor editor =
773                 mContext.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
774                     .edit()
775                     .remove(SHARED_PREFS_AVAILABLE_PIN_BASE_KEY + slotId)
776                     .remove(SHARED_PREFS_REBOOT_PIN_BASE_KEY + slotId);
777 
778         boolean result = true;
779         if (storedPin != null) {
780             // Available PINs are stored with a long-term key, while the PINs in other states
781             // are stored with a short-term key.
782             logd("Saving PIN for slot %d", slotId);
783             if (storedPin.status == PinStatus.AVAILABLE) {
784                 result = savePinInformation(editor, slotId, storedPin,
785                         SHARED_PREFS_AVAILABLE_PIN_BASE_KEY, mLongTermSecretKey);
786             } else {
787                 result = savePinInformation(editor, slotId, storedPin,
788                         SHARED_PREFS_REBOOT_PIN_BASE_KEY, mShortTermSecretKey);
789             }
790         } else {
791             logv("Deleting PIN for slot %d (if existed)", slotId);
792         }
793 
794         mLastCommitResult = editor.commit() && result;
795         return mLastCommitResult;
796     }
797 
798     /**
799      * Store the PIN information to a specific file in non-volatile memory.
800      *
801      * @param editor the {@code SharedPreferences.Editor} to use for storage
802      * @param slotId the slot ID
803      * @param storedPin the PIN information to store
804      * @param baseKey the base name of the key in the {@code SharedPreferences}. The full name is
805      *        derived appending the value of {@code slotId}.
806      * @param secretKey the key used for encryption/decryption
807      * @return true if the operation was successful, false otherwise
808      */
savePinInformation(SharedPreferences.Editor editor, int slotId, StoredPin storedPin, String baseKey, SecretKey secretKey)809     private boolean savePinInformation(SharedPreferences.Editor editor, int slotId,
810             StoredPin storedPin, String baseKey, SecretKey secretKey) {
811         if (secretKey == null) {
812             // Secret key for encryption is missing
813             return false;
814         }
815         if (slotId != storedPin.slotId) {
816             loge("Save PIN: the slotId does not match (%d != %d)", slotId, storedPin.slotId);
817             return false;
818         }
819 
820         logv("Save PIN: %s", storedPin.toString());
821 
822         byte[] encryptedPin = encrypt(secretKey, StoredPin.toByteArray(storedPin));
823         if (encryptedPin.length > 0) {
824             editor.putString(
825                     baseKey + slotId, Base64.encodeToString(encryptedPin, Base64.DEFAULT));
826             return true;
827         } else {
828             return false;
829         }
830     }
831 
832     /** Stored PIN information for slot {@code slotId} in RAM. */
savePinInformationToRam(int slotId, @Nullable StoredPin storedPin)833     private boolean savePinInformationToRam(int slotId, @Nullable StoredPin storedPin) {
834         // Clear the RAM in all cases, to avoid leaking any previous PIN.
835         cleanRamStorage(slotId);
836 
837         if (storedPin == null) {
838             return true;
839         }
840 
841         if (storedPin.status == PinStatus.AVAILABLE) {
842             byte[] encryptedPin = encrypt(mLongTermSecretKey, StoredPin.toByteArray(storedPin));
843             if (encryptedPin != null && encryptedPin.length > 0) {
844                 logd("Saving PIN for slot %d in RAM", slotId);
845                 mRamStorage.put(slotId, encryptedPin);
846                 return true;
847             }
848         }
849         return false;
850     }
851 
852 
853     /** Erases all the PINs stored in RAM before a secure device is unlocked. */
cleanRamStorage()854     private void cleanRamStorage() {
855         int slotCount = getSlotCount();
856         for (int slotId = 0; slotId < slotCount; slotId++) {
857             cleanRamStorage(slotId);
858         }
859     }
860 
861     /** Erases the PIN of slot {@code slotId} stored in RAM before a secure device is unlocked. */
cleanRamStorage(int slotId)862     private void cleanRamStorage(int slotId) {
863         if (mRamStorage != null) {
864             byte[] data = mRamStorage.get(slotId);
865             if (data != null) {
866                 Arrays.fill(data, (byte) 0);
867             }
868             mRamStorage.delete(slotId);
869         }
870     }
871 
872     /**
873      * Verifies all pending PIN codes that are ready for verification.
874      *
875      * The PIN verificartion is done if the PIN state is VERIFICATION_READY and the SIM
876      * card has the PIN enabled and not verified.
877      */
verifyPendingPins()878     private void verifyPendingPins() {
879         int slotCount = getSlotCount();
880         for (int slotId = 0; slotId < slotCount; slotId++) {
881             if (isPinState(slotId, PINSTATE_ENABLED_NOT_VERIFIED)) {
882                 verifyPendingPin(slotId);
883             }
884         }
885     }
886 
887     /** Verifies the PIN code for a given SIM card in slot {@code slotId}. */
verifyPendingPin(int slotId)888     private void verifyPendingPin(int slotId) {
889         // We intentionally invoke getPin() here, as it updates the status and makes sure that
890         // same PIN is not used more than once
891         String pin = getPin(slotId, getIccid(slotId));
892         if (pin.isEmpty()) {
893             // PIN is not available for verification: return.
894             return;
895         }
896 
897         logd("Perform automatic verification of PIN in slot %d", slotId);
898 
899         UiccProfile profile = UiccController.getInstance().getUiccProfileForPhone(slotId);
900         if (profile != null) {
901             Message onComplete = obtainMessage(SUPPLY_PIN_COMPLETE);
902             onComplete.arg2 = slotId;  // arg1 is the number of remaining attempts in the response
903             profile.supplyPin(pin, onComplete);
904         } else {
905             logd("Perform automatic verification of PIN in slot %d not possible", slotId);
906         }
907     }
908 
909     /** Returns the boot count. */
getBootCount()910     private int getBootCount() {
911         return Settings.Global.getInt(
912                 mContext.getContentResolver(),
913                 Settings.Global.BOOT_COUNT,
914                 -1);
915     }
916 
917     /** Returns the number of available SIM slots. */
getSlotCount()918     private int getSlotCount() {
919         // Count the number of slots as the number of Phones.
920         // At power up, it is possible that number of phones is still unknown, so we query
921         // TelephonyManager for it.
922         try {
923             return PhoneFactory.getPhones().length;
924         } catch (Exception ex) {
925             return TelephonyManager.getDefault().getActiveModemCount();
926         }
927     }
928 
929     /**
930      * Saves the number of cached PINs ready for verification after reboot and returns the
931      * previous value.
932      */
saveNumberOfCachedPins(int storedCount)933     private int saveNumberOfCachedPins(int storedCount) {
934         SharedPreferences sharedPrefs =
935                 mContext.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE);
936 
937         int previousValue = sharedPrefs.getInt(SHARED_PREFS_STORED_PINS, 0);
938         sharedPrefs.edit().putInt(SHARED_PREFS_STORED_PINS, storedCount).commit();
939         return previousValue;
940     }
941 
startTimer(int duration)942     private boolean startTimer(int duration) {
943         removeMessages(TIMER_EXPIRATION_EVENT);
944         return duration > 0 ? sendEmptyMessageDelayed(TIMER_EXPIRATION_EVENT, duration) : true;
945     }
946 
947     /** Returns the ICCID of the SIM card for the given {@code slotId}. */
getIccid(int slotId)948     private String getIccid(int slotId) {
949         Phone phone = PhoneFactory.getPhone(slotId);
950         return phone != null ? phone.getFullIccSerialNumber() : "";
951     }
952 
validatePin(String pin)953     private boolean validatePin(String pin) {
954         return pin != null && pin.length() >= MIN_PIN_LENGTH && pin.length() <= MAX_PIN_LENGTH;
955     }
956 
validateIccid(String iccid)957     private boolean validateIccid(String iccid) {
958         return iccid != null && iccid.length() >= MIN_ICCID_LENGTH;
959     }
960 
validateSlotId(int slotId)961     private boolean validateSlotId(int slotId) {
962         return slotId >= 0 && slotId < getSlotCount();
963     }
964 
965     /** Checks if the PIN status of the SIM in slot {@code slotId} is a given {@code PinState}. */
isPinState(int slotId, PinState pinState)966     private boolean isPinState(int slotId, PinState pinState) {
967         UiccProfile profile = UiccController.getInstance().getUiccProfileForPhone(slotId);
968         if (profile != null) {
969             // Loop thru all possible app families to identify at least one that is available in
970             // order to check the PIN state.
971             int[] families = {
972                     UiccController.APP_FAM_3GPP,
973                     UiccController.APP_FAM_3GPP2,
974                     UiccController.APP_FAM_IMS };
975             for (int i = 0; i < families.length; i++) {
976                 UiccCardApplication app = profile.getApplication(i);
977                 if (app != null) {
978                     return app.getPin1State() == pinState;
979                 }
980             }
981         }
982         return false;
983     }
984 
985     /** Returns if the PIN cache is allowed for a given slot. */
isCacheAllowed(int slotId)986     private boolean isCacheAllowed(int slotId) {
987         return isCacheAllowedByDevice() && isCacheAllowedByCarrier(slotId);
988     }
989 
990     /** Returns if the PIN cache is allowed by the device. */
isCacheAllowedByDevice()991     private boolean isCacheAllowedByDevice() {
992         if (!mContext.getResources().getBoolean(
993                 R.bool.config_allow_pin_storage_for_unattended_reboot)) {
994             logv("Pin caching disabled in resources");
995             return false;
996         }
997         return true;
998     }
999 
1000     /** Returns if the PIN cache is allowed by carrier for a given slot. */
isCacheAllowedByCarrier(int slotId)1001     private boolean isCacheAllowedByCarrier(int slotId) {
1002         PersistableBundle config = null;
1003         CarrierConfigManager configManager =
1004                 mContext.getSystemService(CarrierConfigManager.class);
1005         Phone phone = PhoneFactory.getPhone(slotId);
1006         if (configManager != null && phone != null) {
1007             config =
1008                     CarrierConfigManager.getCarrierConfigSubset(
1009                             mContext,
1010                             phone.getSubId(),
1011                             CarrierConfigManager.KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL);
1012         }
1013         if (config == null || config.isEmpty()) {
1014             config = CarrierConfigManager.getDefaultConfig();
1015         }
1016 
1017         return config.getBoolean(
1018                 CarrierConfigManager.KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL, true);
1019     }
1020 
1021     /** Initializes KeyStore and returns the instance. */
1022     @Nullable
initializeKeyStore()1023     private static KeyStore initializeKeyStore() {
1024         KeyStore keyStore = null;
1025         try {
1026             keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
1027             keyStore.load(/*param=*/ null);
1028         } catch (Exception e) {
1029             // Should never happen.
1030             loge("Error loading KeyStore", e);
1031             return null;
1032         }
1033         logv("KeyStore ready");
1034         return keyStore;
1035     }
1036 
1037     /**
1038      * Initializes a secret key and returns it.
1039      *
1040      * @param alias alias of the key in {@link KeyStore}.
1041      * @param createIfAbsent indicates weather the key must be created if not already present.
1042      * @return the {@link SecretKey}, or null if the key does not exist.
1043      */
1044     @Nullable
initializeSecretKey(String alias, boolean createIfAbsent)1045     private SecretKey initializeSecretKey(String alias, boolean createIfAbsent) {
1046         if (mKeyStore == null) {
1047             return null;
1048         }
1049 
1050         SecretKey secretKey = getSecretKey(alias);
1051         if (secretKey != null) {
1052             logd("KeyStore: alias %s exists", alias);
1053             return secretKey;
1054         } else if (createIfAbsent) {
1055             Date expiration =
1056                     KEYSTORE_ALIAS_SHORT_TERM.equals(alias) ? getShortLivedKeyValidityEnd() : null;
1057             boolean isUserAuthRequired =
1058                     !KEYSTORE_ALIAS_LONG_TERM_ALWAYS.equals(alias) && isDeviceSecure();
1059             logd("KeyStore: alias %s does not exist - Creating (exp=%s, auth=%s)",
1060                     alias, expiration != null ? expiration.toString() : "", isUserAuthRequired);
1061             return createSecretKey(alias, expiration, isUserAuthRequired);
1062         } else {
1063             // Nothing to do
1064             logd("KeyStore: alias %s does not exist - Nothing to do", alias);
1065             return null;
1066         }
1067     }
1068 
1069     /**
1070      * Retrieves the secret key previously stored in {@link KeyStore}.
1071      *
1072      * @param alias alias of the key in {@link KeyStore}.
1073      * @return the {@link SecretKey}, or null in case of error or if the key does not exist.
1074      */
1075     @Nullable
getSecretKey(String alias)1076     private SecretKey getSecretKey(String alias) {
1077         try {
1078             final KeyStore.SecretKeyEntry secretKeyEntry =
1079                     (KeyStore.SecretKeyEntry) mKeyStore.getEntry(alias, null);
1080             if (secretKeyEntry != null) {
1081                 return secretKeyEntry.getSecretKey();
1082             }
1083         } catch (Exception e) {
1084             // In case of exception, it means that key exists, but cannot be retrieved
1085             // We delete the old key, so that a new key can be created.
1086             loge("Exception with getting the key " + alias, e);
1087             deleteSecretKey(alias);
1088         }
1089         return null;
1090     }
1091 
1092     /**
1093      * Generates a new secret key in {@link KeyStore}.
1094      *
1095      * @param alias alias of the key in {@link KeyStore}.
1096      * @param expiration expiration of the key, or null if the key does not expire.
1097      * @param isUserAuthRequired indicates if user authentication is required to use the key
1098      * @return the created {@link SecretKey}, or null in case of error
1099      */
1100     @Nullable
createSecretKey(String alias, Date expiration, boolean isUserAuthRequired)1101     private SecretKey createSecretKey(String alias, Date expiration, boolean isUserAuthRequired) {
1102         try {
1103             final KeyGenerator keyGenerator =
1104                     KeyGenerator.getInstance(KEY_ALGORITHM_AES, ANDROID_KEY_STORE_PROVIDER);
1105             KeyGenParameterSpec.Builder keyGenParameterSpec =
1106                     new KeyGenParameterSpec.Builder(alias, PURPOSE_ENCRYPT | PURPOSE_DECRYPT)
1107                         .setBlockModes(BLOCK_MODE_GCM)
1108                         .setEncryptionPaddings(ENCRYPTION_PADDING_NONE);
1109             if (expiration != null) {
1110                 keyGenParameterSpec = keyGenParameterSpec
1111                         .setKeyValidityEnd(expiration);
1112             }
1113             if (isUserAuthRequired) {
1114                 keyGenParameterSpec = keyGenParameterSpec
1115                         .setUserAuthenticationRequired(true)
1116                         .setUserAuthenticationParameters(Integer.MAX_VALUE, AUTH_DEVICE_CREDENTIAL);
1117             }
1118             keyGenerator.init(keyGenParameterSpec.build());
1119             return keyGenerator.generateKey();
1120         } catch (Exception e) {
1121             loge("Create key exception", e);
1122             return null;
1123         }
1124     }
1125 
1126     /** Returns the validity end of a new short-lived key, or null if key does not expire. */
1127     @Nullable
getShortLivedKeyValidityEnd()1128     private Date getShortLivedKeyValidityEnd() {
1129         if (mShortTermSecretKeyDurationMinutes > 0) {
1130             Calendar calendar = Calendar.getInstance();
1131             calendar.setTime(new Date());
1132             calendar.add(Calendar.MINUTE, mShortTermSecretKeyDurationMinutes);
1133             return calendar.getTime();
1134         } else {
1135             return null;
1136         }
1137     }
1138 
1139     /** Deletes the short term key from KeyStore, if it exists. */
deleteSecretKey(String alias)1140     private void deleteSecretKey(String alias) {
1141         if (mKeyStore != null) {
1142             logd("Delete key: %s", alias);
1143             try {
1144                 mKeyStore.deleteEntry(alias);
1145             } catch (Exception e) {
1146                 // Nothing to do. Even if the key removal fails, it becomes unusable.
1147                 loge("Delete key exception");
1148             }
1149         }
1150     }
1151 
1152     /** Returns the encrypted version of {@code input}, or an empty array in case of error. */
encrypt(SecretKey secretKey, byte[] input)1153     private byte[] encrypt(SecretKey secretKey, byte[] input) {
1154         if (secretKey == null) {
1155             loge("Encrypt: Secret key is null");
1156             return new byte[0];
1157         }
1158 
1159         try {
1160             final Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
1161             cipher.init(Cipher.ENCRYPT_MODE, secretKey);
1162 
1163             EncryptedPin encryptedPin = new EncryptedPin();
1164             encryptedPin.iv = cipher.getIV();
1165             encryptedPin.encryptedStoredPin = cipher.doFinal(input);
1166             return EncryptedPin.toByteArray(encryptedPin);
1167         } catch (Exception e) {
1168             loge("Encrypt exception", e);
1169             TelephonyStatsLog.write(PIN_STORAGE_EVENT,
1170                     PIN_STORAGE_EVENT__EVENT__PIN_ENCRYPTION_ERROR, 1, /* package_name= */ "");
1171         }
1172         return new byte[0];
1173     }
1174 
1175     /** Returns the decrypted version of {@code input}, or an empty array in case of error. */
decrypt(SecretKey secretKey, byte[] input)1176     private byte[] decrypt(SecretKey secretKey, byte[] input) {
1177         if (secretKey == null) {
1178             loge("Decrypt: Secret key is null");
1179             return new byte[0];
1180         }
1181 
1182         try {
1183             EncryptedPin encryptedPin = EncryptedPin.parseFrom(input);
1184             if (!ArrayUtils.isEmpty(encryptedPin.encryptedStoredPin)
1185                     && !ArrayUtils.isEmpty(encryptedPin.iv)) {
1186                 final Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
1187                 final GCMParameterSpec spec =
1188                         new GCMParameterSpec(GCM_PARAMETER_TAG_BIT_LEN, encryptedPin.iv);
1189                 cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
1190                 return cipher.doFinal(encryptedPin.encryptedStoredPin);
1191             }
1192         } catch (Exception e) {
1193             loge("Decrypt exception", e);
1194             TelephonyStatsLog.write(PIN_STORAGE_EVENT,
1195                     PIN_STORAGE_EVENT__EVENT__PIN_DECRYPTION_ERROR, 1, /* package_name= */ "");
1196         }
1197         return new byte[0];
1198     }
1199 
logv(String format, Object... args)1200     private static void logv(String format, Object... args) {
1201         if (VDBG) {
1202             Rlog.d(TAG, String.format(format, args));
1203         }
1204     }
1205 
logd(String format, Object... args)1206     private static void logd(String format, Object... args) {
1207         Rlog.d(TAG, String.format(format, args));
1208     }
1209 
loge(String format, Object... args)1210     private static void loge(String format, Object... args) {
1211         Rlog.e(TAG, String.format(format, args));
1212     }
1213 
loge(String msg, Throwable tr)1214     private static void loge(String msg, Throwable tr) {
1215         Rlog.e(TAG, msg, tr);
1216     }
1217 
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1218     void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
1219         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
1220         pw.println("PinStorage:");
1221         pw.increaseIndent();
1222         pw.println("mIsDeviceSecure=" + mIsDeviceSecure);
1223         pw.println("mIsDeviceLocked=" + mIsDeviceLocked);
1224         pw.println("isLongTermSecretKey=" + (boolean) (mLongTermSecretKey != null));
1225         pw.println("isShortTermSecretKey=" + (boolean) (mShortTermSecretKey != null));
1226         pw.println("isCacheAllowedByDevice=" + isCacheAllowedByDevice());
1227         int slotCount = getSlotCount();
1228         for (int i = 0; i < slotCount; i++) {
1229             pw.println("isCacheAllowedByCarrier[" + i + "]=" + isCacheAllowedByCarrier(i));
1230         }
1231         if (VDBG) {
1232             SparseArray<StoredPin> storedPins = loadPinInformation();
1233             for (int i = 0; i < storedPins.size(); i++) {
1234                 pw.println(" pin=" + storedPins.valueAt(i).toString());
1235             }
1236         }
1237         pw.decreaseIndent();
1238     }
1239 }
1240