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