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