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

Commit 88c824ef authored by Jordan Liu's avatar Jordan Liu Committed by Android (Google) Code Review
Browse files

Merge "Use carrier key from carrier config"

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


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


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


/**
/**
@@ -47,6 +51,10 @@ public class CarrierInfoManager {
    */
    */
    private static final int RESET_CARRIER_KEY_RATE_LIMIT = 12 * 60 * 60 * 1000;
    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.
    // Last time the resetCarrierKeysForImsiEncryption API was called successfully.
    private long mLastAccessResetCarrierKey = 0;
    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.
     * 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 keyType whether the key is being used for WLAN or ePDG.
     * @param context
     * @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
     * @return ImsiEncryptionInfo which contains the information, including the public key, to be
     *         used for encryption.
     *         used for encryption.
     */
     */
    public static ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType,
    public static ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType,
                                                                     Context context,
                                                                     Context context,
                                                                     String operatorNumeric) {
                                                                     String operatorNumeric,
                                                                     boolean fallback,
                                                                     int subId) {
        String mcc = "";
        String mcc = "";
        String mnc = "";
        String mnc = "";
        if (!TextUtils.isEmpty(operatorNumeric)) {
        if (!TextUtils.isEmpty(operatorNumeric)) {
            mcc = operatorNumeric.substring(0, 3);
            mcc = operatorNumeric.substring(0, 3);
            mnc = operatorNumeric.substring(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 {
        } else {
            Log.e(LOG_TAG, "Invalid networkOperator: " + operatorNumeric);
            Log.e(LOG_TAG, "Invalid networkOperator: " + operatorNumeric);
            return null;
            return null;
@@ -83,8 +94,55 @@ public class CarrierInfoManager {
                    new String[]{mcc, mnc, String.valueOf(keyType)}, null);
                    new String[]{mcc, mnc, String.valueOf(keyType)}, null);
            if (findCursor == null || !findCursor.moveToFirst()) {
            if (findCursor == null || !findCursor.moveToFirst()) {
                Log.d(LOG_TAG, "No rows found for keyType: " + keyType);
                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;
                    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) {
            if (findCursor.getCount() > 1) {
                Log.e(LOG_TAG, "More than 1 row found for the keyType: " + keyType);
                Log.e(LOG_TAG, "More than 1 row found for the keyType: " + keyType);
            }
            }
+22 −10
Original line number Original line Diff line number Diff line
@@ -185,7 +185,7 @@ public class CarrierKeyDownloadManager extends Handler {
        if (carrierUsesKeys()) {
        if (carrierUsesKeys()) {
            if (areCarrierKeysAbsentOrExpiring()) {
            if (areCarrierKeysAbsentOrExpiring()) {
                boolean downloadStartedSuccessfully = downloadKey();
                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
                // keys, we'll still want to renew the alarms, and try downloading the key a day
                // later.
                // later.
                if (!downloadStartedSuccessfully) {
                if (!downloadStartedSuccessfully) {
@@ -231,7 +231,7 @@ public class CarrierKeyDownloadManager extends Handler {
                continue;
                continue;
            }
            }
            ImsiEncryptionInfo imsiEncryptionInfo =
            ImsiEncryptionInfo imsiEncryptionInfo =
                    mPhone.getCarrierInfoForImsiEncryption(key_type);
                    mPhone.getCarrierInfoForImsiEncryption(key_type, false);
            if (imsiEncryptionInfo != null && imsiEncryptionInfo.getExpirationTime() != null) {
            if (imsiEncryptionInfo != null && imsiEncryptionInfo.getExpirationTime() != null) {
                if (minExpirationDate > imsiEncryptionInfo.getExpirationTime().getTime()) {
                if (minExpirationDate > imsiEncryptionInfo.getExpirationTime().getTime()) {
                    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 carrierKeyDownloadIntent = PendingIntent.getBroadcast(mContext, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, minExpirationDate, carrierKeyDownloadIntent);
        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));
                + new Date(minExpirationDate));
    }
    }


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


@@ -520,8 +531,10 @@ public class CarrierKeyDownloadManager extends Handler {
            if (!isKeyEnabled(key_type)) {
            if (!isKeyEnabled(key_type)) {
                continue;
                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 =
            ImsiEncryptionInfo imsiEncryptionInfo =
                    mPhone.getCarrierInfoForImsiEncryption(key_type);
                    mPhone.getCarrierInfoForImsiEncryption(key_type, false);
            if (imsiEncryptionInfo == null) {
            if (imsiEncryptionInfo == null) {
                Log.d(LOG_TAG, "Key not found for: " + key_type);
                Log.d(LOG_TAG, "Key not found for: " + key_type);
                return true;
                return true;
@@ -553,7 +566,6 @@ public class CarrierKeyDownloadManager extends Handler {
            // TODO(b/128550341): Implement the logic to minimize using metered network such as
            // TODO(b/128550341): Implement the logic to minimize using metered network such as
            // LTE for downloading a certificate.
            // LTE for downloading a certificate.
            request.setAllowedOverMetered(mAllowedOverMeteredNetwork);
            request.setAllowedOverMetered(mAllowedOverMeteredNetwork);
            request.setVisibleInDownloadsUi(false);
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
            request.addRequestHeader("Accept-Encoding", "gzip");
            request.addRequestHeader("Accept-Encoding", "gzip");
            Long carrierKeyDownloadRequestId = mDownloadManager.enqueue(request);
            Long carrierKeyDownloadRequestId = mDownloadManager.enqueue(request);
@@ -566,7 +578,7 @@ public class CarrierKeyDownloadManager extends Handler {
            editor.putString(MCC_MNC_PREF_TAG + slotId, mccMnc);
            editor.putString(MCC_MNC_PREF_TAG + slotId, mccMnc);
            editor.commit();
            editor.commit();
        } catch (Exception e) {
        } 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 false;
        }
        }
        return true;
        return true;
+2 −2
Original line number Original line Diff line number Diff line
@@ -1865,11 +1865,11 @@ public class GsmCdmaPhone extends Phone {
    }
    }


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


    @Override
    @Override
+3 −1
Original line number Original line Diff line number Diff line
@@ -3801,12 +3801,14 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    /**
    /**
     * Returns Carrier specific information that will be used to encrypt the IMSI and IMPI.
     * 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 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
     * @return ImsiEncryptionInfo which includes the Key Type, the Public Key
     *        {@link java.security.PublicKey} and the Key Identifier.
     *        {@link java.security.PublicKey} and the Key Identifier.
     *        The keyIdentifier This is used by the server to help it locate the private key to
     *        The keyIdentifier This is used by the server to help it locate the private key to
     *        decrypt the permanent identity.
     *        decrypt the permanent identity.
     */
     */
    public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) {
    public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType, boolean fallback) {
        return null;
        return null;
    }
    }


+2 −1
Original line number Original line 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.
     * 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 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
     * @return ImsiEncryptionInfo which includes the Key Type, the Public Key
     *        {@link java.security.PublicKey} and the Key Identifier.
     *        {@link java.security.PublicKey} and the Key Identifier.
     *        The keyIdentifier This is used by the server to help it locate the private key to
     *        The keyIdentifier This is used by the server to help it locate the private key to
     *        decrypt the permanent identity.
     *        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.
     * Resets the Carrier Keys, by deleting them from the database and sending a download intent.
Loading