Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2fd2d0d authored by Jordan Liu's avatar Jordan Liu Committed by Gerrit Code Review
Browse files

Merge "Use carrier key from carrier config"

parents c3532228 512a7d2e
Loading
Loading
Loading
Loading
+61 −3
Original line number Diff line number Diff line
@@ -22,16 +22,20 @@ import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteConstraintException;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.ImsiEncryptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

import com.android.internal.telephony.metrics.TelephonyMetrics;

import java.security.PublicKey;
import java.util.Date;

/**
@@ -47,6 +51,10 @@ public class CarrierInfoManager {
    */
    private static final int RESET_CARRIER_KEY_RATE_LIMIT = 12 * 60 * 60 * 1000;

    // Key ID used with the backup key from carrier config
    private static final String EPDG_BACKUP_KEY_ID = "backup_key_from_carrier_config_epdg";
    private static final String WLAN_BACKUP_KEY_ID = "backup_key_from_carrier_config_wlan";

    // Last time the resetCarrierKeysForImsiEncryption API was called successfully.
    private long mLastAccessResetCarrierKey = 0;

@@ -54,18 +62,21 @@ public class CarrierInfoManager {
     * Returns Carrier specific information that will be used to encrypt the IMSI and IMPI.
     * @param keyType whether the key is being used for WLAN or ePDG.
     * @param context
     * @param fallback whether to fallback to the IMSI key info stored in carrier config
     * @return ImsiEncryptionInfo which contains the information, including the public key, to be
     *         used for encryption.
     */
    public static ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType,
                                                                     Context context,
                                                                     String operatorNumeric) {
                                                                     String operatorNumeric,
                                                                     boolean fallback,
                                                                     int subId) {
        String mcc = "";
        String mnc = "";
        if (!TextUtils.isEmpty(operatorNumeric)) {
            mcc = operatorNumeric.substring(0, 3);
            mnc = operatorNumeric.substring(3);
            Log.i(LOG_TAG, "using values for mnc, mcc: " + mnc + "," + mcc);
            Log.i(LOG_TAG, "using values for mcc, mnc: " + mcc + "," + mnc);
        } else {
            Log.e(LOG_TAG, "Invalid networkOperator: " + operatorNumeric);
            return null;
@@ -83,8 +94,55 @@ public class CarrierInfoManager {
                    new String[]{mcc, mnc, String.valueOf(keyType)}, null);
            if (findCursor == null || !findCursor.moveToFirst()) {
                Log.d(LOG_TAG, "No rows found for keyType: " + keyType);
                if (!fallback) {
                    Log.d(LOG_TAG, "Skipping fallback logic");
                    return null;
                }
                // return carrier config key as fallback
                CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
                        context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
                if (carrierConfigManager == null) {
                    Log.d(LOG_TAG, "Could not get CarrierConfigManager for backup key");
                    return null;
                }
                if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                    Log.d(LOG_TAG, "Could not get carrier config with invalid subId");
                    return null;
                }
                PersistableBundle b = carrierConfigManager.getConfigForSubId(subId);
                if (b == null) {
                    Log.d(LOG_TAG, "Could not get carrier config bundle for backup key");
                    return null;
                }
                int keyAvailabilityBitmask = b.getInt(
                        CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT);
                if (!CarrierKeyDownloadManager.isKeyEnabled(keyType, keyAvailabilityBitmask)) {
                    Log.d(LOG_TAG, "Backup key does not have matching keyType. keyType=" + keyType
                            + " keyAvailability=" + keyAvailabilityBitmask);
                    return null;
                }
                String keyString = null;
                String keyId = null;
                if (keyType == TelephonyManager.KEY_TYPE_EPDG) {
                    keyString = b.getString(
                            CarrierConfigManager.IMSI_CARRIER_PUBLIC_KEY_EPDG_STRING);
                    keyId = EPDG_BACKUP_KEY_ID;
                } else if (keyType == TelephonyManager.KEY_TYPE_WLAN) {
                    keyString = b.getString(
                            CarrierConfigManager.IMSI_CARRIER_PUBLIC_KEY_WLAN_STRING);
                    keyId = WLAN_BACKUP_KEY_ID;
                }
                if (TextUtils.isEmpty(keyString)) {
                    Log.d(LOG_TAG,
                            "Could not get carrier config key string for backup key. keyType="
                                    + keyType);
                    return null;
                }
                Pair<PublicKey, Long> keyInfo =
                        CarrierKeyDownloadManager.getKeyInformation(keyString.getBytes());
                return new ImsiEncryptionInfo(mcc, mnc, keyType, keyId,
                        keyInfo.first, new Date(keyInfo.second));
            }
            if (findCursor.getCount() > 1) {
                Log.e(LOG_TAG, "More than 1 row found for the keyType: " + keyType);
            }
+22 −10
Original line number Diff line number Diff line
@@ -185,7 +185,7 @@ public class CarrierKeyDownloadManager extends Handler {
        if (carrierUsesKeys()) {
            if (areCarrierKeysAbsentOrExpiring()) {
                boolean downloadStartedSuccessfully = downloadKey();
                // if the download was attemped, but not started successfully, and if carriers uses
                // if the download was attempted, but not started successfully, and if carriers uses
                // keys, we'll still want to renew the alarms, and try downloading the key a day
                // later.
                if (!downloadStartedSuccessfully) {
@@ -231,7 +231,7 @@ public class CarrierKeyDownloadManager extends Handler {
                continue;
            }
            ImsiEncryptionInfo imsiEncryptionInfo =
                    mPhone.getCarrierInfoForImsiEncryption(key_type);
                    mPhone.getCarrierInfoForImsiEncryption(key_type, false);
            if (imsiEncryptionInfo != null && imsiEncryptionInfo.getExpirationTime() != null) {
                if (minExpirationDate > imsiEncryptionInfo.getExpirationTime().getTime()) {
                    minExpirationDate = imsiEncryptionInfo.getExpirationTime().getTime();
@@ -275,7 +275,7 @@ public class CarrierKeyDownloadManager extends Handler {
        PendingIntent carrierKeyDownloadIntent = PendingIntent.getBroadcast(mContext, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, minExpirationDate, carrierKeyDownloadIntent);
        Log.d(LOG_TAG, "setRenewelAlarm: action=" + intent.getAction() + " time="
        Log.d(LOG_TAG, "setRenewalAlarm: action=" + intent.getAction() + " time="
                + new Date(minExpirationDate));
    }

@@ -387,8 +387,10 @@ public class CarrierKeyDownloadManager extends Handler {
        mURL = b.getString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING);
        mAllowedOverMeteredNetwork = b.getBoolean(
                KEY_ALLOW_METERED_NETWORK_FOR_CERT_DOWNLOAD_BOOL);
        if (TextUtils.isEmpty(mURL) || mKeyAvailability == 0) {
            Log.d(LOG_TAG, "Carrier not enabled or invalid values");
        if (mKeyAvailability == 0 || TextUtils.isEmpty(mURL)) {
            Log.d(LOG_TAG,
                    "Carrier not enabled or invalid values. mKeyAvailability=" + mKeyAvailability
                            + " mURL=" + mURL);
            return false;
        }
        for (int key_type : CARRIER_KEY_TYPES) {
@@ -505,7 +507,16 @@ public class CarrierKeyDownloadManager extends Handler {
    @VisibleForTesting
    public boolean isKeyEnabled(int keyType) {
        // since keytype has values of 1, 2.... we need to subtract 1 from the keytype.
        int returnValue = (mKeyAvailability >> (keyType - 1)) & 1;
        return isKeyEnabled(keyType, mKeyAvailability);
    }

    /**
     * introspects the mKeyAvailability bitmask
     * @return true if the digit at position k is 1, else false.
     */
    public static boolean isKeyEnabled(int keyType, int keyAvailability) {
        // since keytype has values of 1, 2.... we need to subtract 1 from the keytype.
        int returnValue = (keyAvailability >> (keyType - 1)) & 1;
        return (returnValue == 1) ? true : false;
    }

@@ -520,8 +531,10 @@ public class CarrierKeyDownloadManager extends Handler {
            if (!isKeyEnabled(key_type)) {
                continue;
            }
            // get encryption info with fallback=false so that we attempt a download even if there's
            // backup info stored in carrier config
            ImsiEncryptionInfo imsiEncryptionInfo =
                    mPhone.getCarrierInfoForImsiEncryption(key_type);
                    mPhone.getCarrierInfoForImsiEncryption(key_type, false);
            if (imsiEncryptionInfo == null) {
                Log.d(LOG_TAG, "Key not found for: " + key_type);
                return true;
@@ -553,7 +566,6 @@ public class CarrierKeyDownloadManager extends Handler {
            // TODO(b/128550341): Implement the logic to minimize using metered network such as
            // LTE for downloading a certificate.
            request.setAllowedOverMetered(mAllowedOverMeteredNetwork);
            request.setVisibleInDownloadsUi(false);
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
            request.addRequestHeader("Accept-Encoding", "gzip");
            Long carrierKeyDownloadRequestId = mDownloadManager.enqueue(request);
@@ -566,7 +578,7 @@ public class CarrierKeyDownloadManager extends Handler {
            editor.putString(MCC_MNC_PREF_TAG + slotId, mccMnc);
            editor.commit();
        } catch (Exception e) {
            Log.e(LOG_TAG, "exception trying to dowload key from url: " + mURL);
            Log.e(LOG_TAG, "exception trying to download key from url: " + mURL);
            return false;
        }
        return true;
+2 −2
Original line number Diff line number Diff line
@@ -1862,11 +1862,11 @@ public class GsmCdmaPhone extends Phone {
    }

    @Override
    public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) {
    public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType, boolean fallback) {
        String operatorNumeric = TelephonyManager.from(mContext)
                .getSimOperatorNumericForPhone(mPhoneId);
        return CarrierInfoManager.getCarrierInfoForImsiEncryption(keyType,
                mContext, operatorNumeric);
                mContext, operatorNumeric, fallback, getSubId());
    }

    @Override
+3 −1
Original line number Diff line number Diff line
@@ -3795,12 +3795,14 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    /**
     * Returns Carrier specific information that will be used to encrypt the IMSI and IMPI.
     * @param keyType whether the key is being used for WLAN or ePDG.
     * @param fallback whether or not to fall back to the encryption key info stored in carrier
     *                 config
     * @return ImsiEncryptionInfo which includes the Key Type, the Public Key
     *        {@link java.security.PublicKey} and the Key Identifier.
     *        The keyIdentifier This is used by the server to help it locate the private key to
     *        decrypt the permanent identity.
     */
    public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) {
    public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType, boolean fallback) {
        return null;
    }

+2 −1
Original line number Diff line number Diff line
@@ -1046,12 +1046,13 @@ public interface PhoneInternalInterface {
    /**
     * Returns Carrier specific information that will be used to encrypt the IMSI and IMPI.
     * @param keyType whether the key is being used for WLAN or ePDG.
     * @param fallback whether to fall back to the encryption key stored in carrier config
     * @return ImsiEncryptionInfo which includes the Key Type, the Public Key
     *        {@link java.security.PublicKey} and the Key Identifier.
     *        The keyIdentifier This is used by the server to help it locate the private key to
     *        decrypt the permanent identity.
     */
    public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType);
    ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType, boolean fallback);

    /**
     * Resets the Carrier Keys, by deleting them from the database and sending a download intent.
Loading