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