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

Commit 5f6aebfc authored by Hai Shalom's avatar Hai Shalom Committed by Etan Cohen
Browse files

[Encrypted IMSI] Make WLAN the default certificate type

The 3GPP spec for encrypted IMSI certificate specifies
"key-identifier" and "public-key" String properties, but does not
specify "key-type" property which was a mandatory requirement in the
implementation prior to this change. Make the "WLAN" key type as the
default type, so if it is not provided by the carrier, then the logic
would treat the certificate as WLAN type.

Bug: 134604306
Test: Install carrier SIM and auto connect to carrier Wi-Fi network
Test: atest CarrierKeyDownloadMgrTest
Change-Id: Ic749eb7ca956ff7ef6d86e481f56f95562c5dced
parent 439fdc37
Loading
Loading
Loading
Loading
+15 −11
Original line number Diff line number Diff line
@@ -96,8 +96,6 @@ public class CarrierKeyDownloadManager extends Handler {
    private static final String SEPARATOR = ":";

    private static final String JSON_CERTIFICATE = "certificate";
    // This is a hack to accommodate certain Carriers who insists on using the public-key
    // field to store the certificate. We'll just use which-ever is not null.
    private static final String JSON_CERTIFICATE_ALTERNATE = "public-key";
    private static final String JSON_TYPE = "key-type";
    private static final String JSON_IDENTIFIER = "key-identifier";
@@ -111,7 +109,6 @@ public class CarrierKeyDownloadManager extends Handler {

    private static final int[] CARRIER_KEY_TYPES = {TelephonyManager.KEY_TYPE_EPDG,
            TelephonyManager.KEY_TYPE_WLAN};
    private static final int UNINITIALIZED_KEY_TYPE = -1;

    private final Phone mPhone;
    private final Context mContext;
@@ -451,20 +448,27 @@ public class CarrierKeyDownloadManager extends Handler {
            JSONArray keys = jsonObj.getJSONArray(JSON_CARRIER_KEYS);
            for (int i = 0; i < keys.length(); i++) {
                JSONObject key = keys.getJSONObject(i);
                // This is a hack to accommodate certain carriers who insist on using the public-key
                // field to store the certificate. We'll just use which-ever is not null.
                // Support both "public-key" and "certificate" String property.
                // "certificate" is a more accurate description, however, the 3GPP draft spec
                // S3-170116, "Privacy Protection for EAP-AKA" section 4.3 mandates the use of
                // "public-key".
                String cert = null;
                if (key.has(JSON_CERTIFICATE)) {
                    cert = key.getString(JSON_CERTIFICATE);
                } else {
                    cert = key.getString(JSON_CERTIFICATE_ALTERNATE);
                }
                // The 3GPP draft spec 3GPP draft spec S3-170116, "Privacy Protection for EAP-AKA"
                // section 4.3, does not specify any key-type property. To be compatible with these
                // networks, the logic defaults to WLAN type if not specified.
                int type = TelephonyManager.KEY_TYPE_WLAN;
                if (key.has(JSON_TYPE)) {
                    String typeString = key.getString(JSON_TYPE);
                int type = UNINITIALIZED_KEY_TYPE;
                if (typeString.equals(JSON_TYPE_VALUE_WLAN)) {
                    type = TelephonyManager.KEY_TYPE_WLAN;
                } else if (typeString.equals(JSON_TYPE_VALUE_EPDG)) {
                    if (typeString.equals(JSON_TYPE_VALUE_EPDG)) {
                        type = TelephonyManager.KEY_TYPE_EPDG;
                    } else if (!typeString.equals(JSON_TYPE_VALUE_WLAN)) {
                        Log.e(LOG_TAG, "Invalid key-type specified: " + typeString);
                    }
                }
                String identifier = key.getString(JSON_IDENTIFIER);
                ByteArrayInputStream inStream = new ByteArrayInputStream(cert.getBytes());
+43 −14
Original line number Diff line number Diff line
@@ -15,6 +15,19 @@
 */
package com.android.internal.telephony;

import static android.preference.PreferenceManager.getDefaultSharedPreferences;

import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
@@ -23,6 +36,7 @@ import android.os.HandlerThread;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.ImsiEncryptionInfo;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Pair;

@@ -44,18 +58,6 @@ import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import static android.preference.PreferenceManager.getDefaultSharedPreferences;

import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class CarrierKeyDownloadMgrTest extends TelephonyTest {

    private static final String LOG_TAG = "CarrierKeyDownloadManager";
@@ -66,12 +68,14 @@ public class CarrierKeyDownloadMgrTest extends TelephonyTest {
    private String mURL = "http://www.google.com";

    private static final String CERT = "-----BEGIN CERTIFICATE-----\r\nMIIFjzCCBHegAwIBAgIUPxj3SLif82Ky1RlUy8p2EWJCh8MwDQYJKoZIhvcNAQELBQAwgY0xCzAJBgNVBAYTAk5MMRIwEAYDVQQHEwlBbXN0ZXJkYW0xJTAjBgNVBAoTHFZlcml6b24gRW50ZXJwcmlzZSBTb2x1dGlvbnMxEzARBgNVBAsTCkN5YmVydHJ1c3QxLjAsBgNVBAMTJVZlcml6b24gUHVibGljIFN1cmVTZXJ2ZXIgQ0EgRzE0LVNIQTIwHhcNMTcwODE0MTc0MzM4WhcNMTkwODE0MTc0MzM4WjCBmTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFjAUBgNVBAcTDUJhc2tpbmcgUmlkZ2UxIjAgBgNVBAoTGVZlcml6b24gRGF0YSBTZXJ2aWNlcyBMTEMxHzAdBgNVBAsTFk5ldHdvcmsgU3lzdGVtIFN1cHBvcnQxGDAWBgNVBAMTD3ZpMWx2Lmltc3ZtLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALUQKWTHi4Hjpd1LQwJ87RXa0Rs3rVonvVevliqdUH5BikjhAzvIqwPSXeRQqkaRTFIyp0NKcNqGdjAaHRo43gdHeWSH331sS6CMZDg988gZznskzCqJJo6ii5FuLC8qe2YDsHxT+CefXev2rn6Bj1ei2X74uZsy5KlkBRZfFHtPdK6/EK5TpzrvcXfDyOK1rn8FTno1bQOTAhL39GPcLhdrXV7AN+lu+EBpdCqlTdcoDxsqavi/91MwUIVEzxJmycKloT6OWfU44r7+L5SYYgc88NTaGL/BvCFwHRIa1ZgYSGeAPes45792MGG7tfr/ttAGp9UEwTv2zWTxzWnRP/UCAwEAAaOCAdcwggHTMAwGA1UdEwEB/wQCMAAwTAYDVR0gBEUwQzBBBgkrBgEEAbE+ATIwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly9zZWN1cmUub21uaXJvb3QuY29tL3JlcG9zaXRvcnkwgakGCCsGAQUFBwEBBIGcMIGZMC0GCCsGAQUFBzABhiFodHRwOi8vdnBzc2cxNDIub2NzcC5vbW5pcm9vdC5jb20wMwYIKwYBBQUHMAKGJ2h0dHA6Ly9jYWNlcnQub21uaXJvb3QuY29tL3Zwc3NnMTQyLmNydDAzBggrBgEFBQcwAoYnaHR0cDovL2NhY2VydC5vbW5pcm9vdC5jb20vdnBzc2cxNDIuZGVyMBoGA1UdEQQTMBGCD3ZpMWx2Lmltc3ZtLmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFOQtu5EBZSYftHo/oxUlpM6MRDM7MD4GA1UdHwQ3MDUwM6AxoC+GLWh0dHA6Ly92cHNzZzE0Mi5jcmwub21uaXJvb3QuY29tL3Zwc3NnMTQyLmNybDAdBgNVHQ4EFgQUv5SaSyNM/yXw1v0N9TNpjsFCaPcwDQYJKoZIhvcNAQELBQADggEBACNJusTULj1KyV4RwiskKfp4wI9Hsz3ESbZS/ijF9D57BQ0UwkELU9r6rEAhsYLUvMq4sDhDbYIdupgP4MBzFnjkKult7VQm5W3nCcuHgXYFAJ9Y1a4OZAo/4hrHj70W9TsQ1ioSMjUT4F8bDUYZI0kcyH8e/+2DaTsLUpHw3L+Keu8PsJVBLnvcKJjWrZD/Bgd6JuaTX2G84i0rY0GJuO9CxLNJa6n61Mz5cqLYIuwKgiVgTA2n71YITyFICOFPFX1vSx35AWvD6aVYblxtC8mpCdF2h4s1iyrpXeji2GCJLwsNVtTtNQ4zWX3Gnq683wzkYZeyOHUyftIgAQZ+HsY=\r\n-----END CERTIFICATE-----";


    private static final long CERT_EXPIRATION = 1565804618000L; //milliseconds since the epoch
    private String mJsonStr = "{ \"carrier-keys\": [ { \"certificate\": \"" + CERT + "\", \"key-type\": \"WLAN\", \"key-identifier\": \"key1=value\", \"expiration-date\": 1502577746000 }, { \"certificate\": \"" + CERT + "\", \"key-type\": \"WLAN\", \"key-identifier\": \"key1=value\", \"expiration-date\": 1502577746000 }]}";

    private String mJsonStr1 = "{ \"carrier-keys\": [ { \"public-key\": \"" + CERT + "\", \"key-type\": \"WLAN\", \"key-identifier\": \"key1=value\", \"expiration-date\": 1502577746000 }, { \"public-key\": \"" + CERT + "\", \"key-type\": \"WLAN\", \"key-identifier\": \"key1=value\", \"expiration-date\": 1502577746000 }]}";

    private String mJsonStr3GppSpec = "{ \"carrier-keys\": [ { \"key-identifier\": \"key1=value\", "
            + "\"public-key\": \"" + CERT + "\"}]}";

    private class CarrierActionAgentHandler extends HandlerThread {

        private CarrierActionAgentHandler(String name) {
@@ -327,4 +331,29 @@ public class CarrierKeyDownloadMgrTest extends TelephonyTest {
        String mccMnc = preferences.getString("CARRIER_KEY_DM_MCC_MNC" + slotId, null);
        assertTrue(mccMnc.equals("310:260"));
    }

    /**
     * Checks if the JSON in 3GPP spec format is parsed correctly, and that WLAN is the key type.
     **/
    @Test
    @SmallTest
    public void testParseJson3GppFormat() {
        ByteArrayInputStream certBytes = new ByteArrayInputStream(CERT.getBytes());
        Reader fRd = new BufferedReader(new InputStreamReader(certBytes));
        PemReader reader = new PemReader(fRd);
        Pair<PublicKey, Long> keyInfo = null;
        try {
            keyInfo = mCarrierKeyDM.getKeyInformation(reader.readPemObject().getContent());
        } catch (Exception e) {
            fail(LOG_TAG + "exception creating public key");
        }
        ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("310", "270",
                TelephonyManager.KEY_TYPE_WLAN, "key1=value", keyInfo.first,
                new Date(CERT_EXPIRATION));
        String mccMnc = "310:270";
        mCarrierKeyDM.parseJsonAndPersistKey(mJsonStr3GppSpec, mccMnc);
        verify(mPhone).setCarrierInfoForImsiEncryption(
                (Matchers.refEq(imsiEncryptionInfo)));
    }

}