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