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