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