Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2017 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 package com.android.internal.telephony;
     17 
     18 import android.app.DownloadManager;
     19 import android.content.Context;
     20 import android.content.Intent;
     21 import android.content.SharedPreferences;
     22 import android.os.HandlerThread;
     23 import android.os.PersistableBundle;
     24 import android.telephony.CarrierConfigManager;
     25 import android.telephony.ImsiEncryptionInfo;
     26 import android.test.suitebuilder.annotation.SmallTest;
     27 import android.util.Pair;
     28 
     29 import com.android.org.bouncycastle.util.io.pem.PemReader;
     30 
     31 import org.junit.After;
     32 import org.junit.Before;
     33 import org.junit.Test;
     34 import org.mockito.Matchers;
     35 import org.mockito.MockitoAnnotations;
     36 
     37 import java.io.BufferedReader;
     38 import java.io.ByteArrayInputStream;
     39 import java.io.InputStreamReader;
     40 import java.io.Reader;
     41 import java.security.PublicKey;
     42 import java.text.SimpleDateFormat;
     43 import java.util.Calendar;
     44 import java.util.Date;
     45 import java.util.GregorianCalendar;
     46 
     47 import static android.preference.PreferenceManager.getDefaultSharedPreferences;
     48 
     49 import static org.junit.Assert.assertFalse;
     50 import static org.junit.Assert.assertTrue;
     51 import static org.junit.Assert.fail;
     52 import static org.mockito.ArgumentMatchers.any;
     53 import static org.mockito.Mockito.anyInt;
     54 import static org.mockito.Mockito.times;
     55 import static org.mockito.Mockito.verify;
     56 import static org.mockito.Mockito.when;
     57 
     58 public class CarrierKeyDownloadMgrTest extends TelephonyTest {
     59 
     60     private static final String LOG_TAG = "CarrierKeyDownloadManager";
     61 
     62     private CarrierKeyDownloadManager mCarrierKeyDM;
     63     private CarrierActionAgentHandler mCarrierActionAgentHandler;
     64 
     65     private String mURL = "http://www.google.com";
     66 
     67     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-----";
     68 
     69 
     70     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 }]}";
     71 
     72     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 }]}";
     73 
     74     private class CarrierActionAgentHandler extends HandlerThread {
     75 
     76         private CarrierActionAgentHandler(String name) {
     77             super(name);
     78         }
     79 
     80         @Override
     81         public void onLooperPrepared() {
     82             mCarrierKeyDM = new CarrierKeyDownloadManager(mPhone);
     83             setReady(true);
     84         }
     85     }
     86 
     87     @Before
     88     public void setUp() throws Exception {
     89         logd("CarrierActionAgentTest +Setup!");
     90         MockitoAnnotations.initMocks(this);
     91         super.setUp(getClass().getSimpleName());
     92         mCarrierActionAgentHandler = new CarrierActionAgentHandler(getClass().getSimpleName());
     93         mCarrierActionAgentHandler.start();
     94         waitUntilReady();
     95         logd("CarrierActionAgentTest -Setup!");
     96     }
     97 
     98     @After
     99     public void tearDown() throws Exception {
    100         mCarrierActionAgentHandler.quit();
    101         super.tearDown();
    102     }
    103 
    104     /* Checks if the expiration date is calculated correctly
    105      * In this case the expiration date should be the next day.
    106      */
    107     @Test
    108     @SmallTest
    109     public void testExpirationDate1Day() {
    110         java.security.PublicKey publicKey = null;
    111         mCarrierKeyDM.mKeyAvailability = 3;
    112         SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd");
    113         Calendar cal = new GregorianCalendar();
    114         cal.add(Calendar.DATE, 6);
    115         Date date = cal.getTime();
    116         Calendar expectedCal = new GregorianCalendar();
    117         expectedCal.add(Calendar.DATE, 1);
    118         String dateExpected = dt.format(expectedCal.getTime());
    119         ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("mcc", "mnc", 1,
    120                 "keyIdentifier", publicKey, date);
    121         when(mPhone.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(imsiEncryptionInfo);
    122         Date expirationDate = new Date(mCarrierKeyDM.getExpirationDate());
    123         assertTrue(dt.format(expirationDate).equals(dateExpected));
    124     }
    125 
    126     /**
    127      * Checks if the expiration date is calculated correctly
    128      * In this case the expiration date should be within the window (7 to 21 days).
    129      **/
    130     @Test
    131     @SmallTest
    132     public void testExpirationDate7Day() {
    133         java.security.PublicKey publicKey = null;
    134         mCarrierKeyDM.mKeyAvailability = 3;
    135         SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd");
    136         Calendar cal = new GregorianCalendar();
    137         cal.add(Calendar.DATE, 30);
    138         Date date = cal.getTime();
    139         Calendar minExpirationCal = new GregorianCalendar();
    140         Calendar maxExpirationCal = new GregorianCalendar();
    141         minExpirationCal.add(Calendar.DATE, 23);
    142         maxExpirationCal.add(Calendar.DATE, 9);
    143         Date minExpirationDate = minExpirationCal.getTime();
    144         Date maxExpirationDate = maxExpirationCal.getTime();
    145         ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("mcc", "mnc", 1,
    146                 "keyIdentifier", publicKey, date);
    147         when(mPhone.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(imsiEncryptionInfo);
    148         Date expirationDate = new Date(mCarrierKeyDM.getExpirationDate());
    149         assertTrue(expirationDate.before(minExpirationDate));
    150         assertTrue(expirationDate.after(maxExpirationDate));
    151     }
    152 
    153     /**
    154      * Checks if the json is parse correctly.
    155      * Verify that setCarrierInfoForImsiEncryption is called with the right params
    156      **/
    157     @Test
    158     @SmallTest
    159     public void testParseJson() {
    160         ByteArrayInputStream certBytes = new ByteArrayInputStream(CERT.getBytes());
    161         Reader fRd = new BufferedReader(new InputStreamReader(certBytes));
    162         PemReader reader = new PemReader(fRd);
    163         Pair<PublicKey, Long> keyInfo = null;
    164         try {
    165             keyInfo = mCarrierKeyDM.getKeyInformation(reader.readPemObject().getContent());
    166         } catch (Exception e) {
    167             fail(LOG_TAG + "exception creating public key");
    168         }
    169         ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("310", "270", 2,
    170                 "key1=value", keyInfo.first, new Date(keyInfo.second));
    171         String mccMnc = "310:270";
    172         mCarrierKeyDM.parseJsonAndPersistKey(mJsonStr, mccMnc);
    173         verify(mPhone, times(2)).setCarrierInfoForImsiEncryption(
    174                 (Matchers.refEq(imsiEncryptionInfo)));
    175     }
    176 
    177     /**
    178      * Checks if the json is parse correctly.
    179      * Same as testParseJason, except that the test looks for the "public-key" field.
    180      **/
    181     @Test
    182     @SmallTest
    183     public void testParseJsonPublicKey() {
    184         ByteArrayInputStream certBytes = new ByteArrayInputStream(CERT.getBytes());
    185         Reader fRd = new BufferedReader(new InputStreamReader(certBytes));
    186         PemReader reader = new PemReader(fRd);
    187         Pair<PublicKey, Long> keyInfo = null;
    188         try {
    189             keyInfo = mCarrierKeyDM.getKeyInformation(reader.readPemObject().getContent());
    190         } catch (Exception e) {
    191             fail(LOG_TAG + "exception creating public key");
    192         }
    193         ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("310", "270", 2,
    194                 "key1=value", keyInfo.first, new Date(keyInfo.second));
    195         String mccMnc = "310:270";
    196         mCarrierKeyDM.parseJsonAndPersistKey(mJsonStr1, mccMnc);
    197         verify(mPhone, times(2)).setCarrierInfoForImsiEncryption(
    198                 (Matchers.refEq(imsiEncryptionInfo)));
    199     }
    200 
    201     /**
    202      * Checks if the json is parse correctly.
    203      * Since the json is bad, we want to verify that savePublicKey is not called.
    204      **/
    205     @Test
    206     @SmallTest
    207     public void testParseBadJsonFail() {
    208         String mccMnc = "310:290";
    209         String badJsonStr = "{badJsonString}";
    210         mCarrierKeyDM.parseJsonAndPersistKey(badJsonStr, mccMnc);
    211         verify(mPhone, times(0)).setCarrierInfoForImsiEncryption(any());
    212     }
    213 
    214     /**
    215      * Checks if the download is valid.
    216      * returns true since the mnc/mcc is valid.
    217      **/
    218     @Test
    219     @SmallTest
    220     public void testIsValidDownload() {
    221         String mccMnc = "310:260";
    222         when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
    223         assertTrue(mCarrierKeyDM.isValidDownload(mccMnc));
    224     }
    225 
    226     /**
    227      * Checks if the download is valid.
    228      * returns false since the mnc/mcc is in-valid.
    229      **/
    230     @Test
    231     @SmallTest
    232     public void testIsValidDownloadFail() {
    233         String mccMnc = "310:290";
    234         when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
    235         assertFalse(mCarrierKeyDM.isValidDownload(mccMnc));
    236     }
    237 
    238     /**
    239      * Tests if the key is enabled.
    240      * tests for all bit-mask value.
    241      **/
    242     @Test
    243     @SmallTest
    244     public void testIsKeyEnabled() {
    245         mCarrierKeyDM.mKeyAvailability = 3;
    246         assertTrue(mCarrierKeyDM.isKeyEnabled(1));
    247         assertTrue(mCarrierKeyDM.isKeyEnabled(2));
    248         mCarrierKeyDM.mKeyAvailability = 2;
    249         assertFalse(mCarrierKeyDM.isKeyEnabled(1));
    250         assertTrue(mCarrierKeyDM.isKeyEnabled(2));
    251         mCarrierKeyDM.mKeyAvailability = 1;
    252         assertTrue(mCarrierKeyDM.isKeyEnabled(1));
    253         assertFalse(mCarrierKeyDM.isKeyEnabled(2));
    254     }
    255 
    256     /**
    257      * Tests sending the ACTION_DOWNLOAD_COMPLETE intent.
    258      * Verify that the alarm will kick-off the next day.
    259      **/
    260     @Test
    261     @SmallTest
    262     public void testDownloadComplete() {
    263         SharedPreferences.Editor editor = getDefaultSharedPreferences(mContext).edit();
    264         String mccMnc = "310:260";
    265         int slotId = mPhone.getPhoneId();
    266         editor.putString("CARRIER_KEY_DM_MCC_MNC" + slotId, mccMnc);
    267         editor.commit();
    268 
    269         SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd");
    270         Calendar expectedCal = new GregorianCalendar();
    271         expectedCal.add(Calendar.DATE, 1);
    272         String dateExpected = dt.format(expectedCal.getTime());
    273 
    274         when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
    275         Intent mIntent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
    276         mContext.sendBroadcast(mIntent);
    277         Date expirationDate = new Date(mCarrierKeyDM.getExpirationDate());
    278         assertTrue(dt.format(expirationDate).equals(dateExpected));
    279     }
    280 
    281     /**
    282      * Test sending the ACTION_CARRIER_CONFIG_CHANGED intent.
    283      * Verify that the right mnc/mcc gets stored in the preferences.
    284      **/
    285     @Test
    286     @SmallTest
    287     public void testCarrierConfigChanged() {
    288         CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
    289                 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
    290         int slotId = mPhone.getPhoneId();
    291         PersistableBundle bundle = carrierConfigManager.getConfigForSubId(slotId);
    292         bundle.putInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, 3);
    293         bundle.putString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, mURL);
    294 
    295         when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
    296         Intent mIntent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
    297         mIntent.putExtra(PhoneConstants.PHONE_KEY, 0);
    298         mContext.sendBroadcast(mIntent);
    299         SharedPreferences preferences = getDefaultSharedPreferences(mContext);
    300         String mccMnc = preferences.getString("CARRIER_KEY_DM_MCC_MNC" + slotId, null);
    301         assertTrue(mccMnc.equals("310:260"));
    302     }
    303 
    304     /**
    305      * Tests sending the INTENT_KEY_RENEWAL_ALARM_PREFIX intent.
    306      * Verify that the right mnc/mcc gets stored in the preferences.
    307      **/
    308     @Test
    309     @SmallTest
    310     public void testAlarmRenewal() {
    311         CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
    312                 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
    313         int slotId = mPhone.getPhoneId();
    314         PersistableBundle bundle = carrierConfigManager.getConfigForSubId(slotId);
    315         bundle.putInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, 3);
    316         bundle.putString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, mURL);
    317 
    318         when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
    319         Intent mIntent = new Intent("com.android.internal.telephony.carrier_key_download_alarm"
    320                 + slotId);
    321         mContext.sendBroadcast(mIntent);
    322         SharedPreferences preferences = getDefaultSharedPreferences(mContext);
    323         String mccMnc = preferences.getString("CARRIER_KEY_DM_MCC_MNC" + slotId, null);
    324         assertTrue(mccMnc.equals("310:260"));
    325     }
    326 }
    327