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