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