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

Commit fb41d485 authored by Cassie's avatar Cassie
Browse files

Make access rule format compatible with GP.

1. Allow a 4F tag with length of 6 and value "FF FF FF FF FF FF".
2. Allow optional tags before the DB tag.

Cherry-picked cleanly from: ag/2772379

Bug: 64021133
Change-Id: If189ad01bd1124d84f93a60bd96426d2555c9c91
Test: Basic telephony sanity
(cherry picked from commit f561305f)
parent 21003bba
Loading
Loading
Loading
Loading
+37 −20
Original line number Diff line number Diff line
@@ -94,6 +94,8 @@ public class UiccCarrierPrivilegeRules extends Handler {
    private static final String TAG_PKG_REF_DO = "CA";
    private static final String TAG_AR_DO = "E3";
    private static final String TAG_PERM_AR_DO = "DB";
    private static final String TAG_AID_REF_DO = "4F";
    private static final String CARRIER_PRIVILEGE_AID = "FFFFFFFFFFFF";

    private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 1;
    private static final int EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE = 2;
@@ -562,16 +564,27 @@ public class UiccCarrierPrivilegeRules extends Handler {
            if (rule.startsWith(TAG_REF_DO)) {
                TLV refDo = new TLV(TAG_REF_DO); //E1
                rule = refDo.parse(rule, false);

                // Skip unrelated rules.
                if (!refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) {
                // Allow 4F tag with a default value "FF FF FF FF FF FF" to be compatible with
                // devices having GP access control enforcer:
                //  - If no 4F tag is present, it's a CP rule.
                //  - If 4F tag has value "FF FF FF FF FF FF", it's a CP rule.
                //  - If 4F tag has other values, it's not a CP rule and Android should ignore it.
                TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); //C1
                if (refDo.value.startsWith(TAG_AID_REF_DO)) {
                    TLV cpDo = new TLV(TAG_AID_REF_DO); //4F
                    String remain = cpDo.parse(refDo.value, false);
                    if (!cpDo.lengthBytes.equals("06") || !cpDo.value.equals(CARRIER_PRIVILEGE_AID)
                            || remain.isEmpty() || !remain.startsWith(TAG_DEVICE_APP_ID_REF_DO)) {
                        return null;
                    }

                TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); //C1
                    tmp = deviceDo.parse(remain, false);
                    certificateHash = deviceDo.value;
                } else if (refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) {
                    tmp = deviceDo.parse(refDo.value, false);
                    certificateHash = deviceDo.value;

                } else {
                    return null;
                }
                if (!tmp.isEmpty()) {
                    if (!tmp.startsWith(TAG_PKG_REF_DO)) {
                        return null;
@@ -585,14 +598,18 @@ public class UiccCarrierPrivilegeRules extends Handler {
            } else if (rule.startsWith(TAG_AR_DO)) {
                TLV arDo = new TLV(TAG_AR_DO); //E3
                rule = arDo.parse(rule, false);

                // Skip unrelated rules.
                if (!arDo.value.startsWith(TAG_PERM_AR_DO)) {
                // Skip all the irrelevant tags (All the optional tags here are two bytes
                // according to the spec GlobalPlatform Secure Element Access Control).
                String remain = arDo.value;
                while (!remain.isEmpty() && !remain.startsWith(TAG_PERM_AR_DO)) {
                    TLV tmpDo = new TLV(remain.substring(0, 2));
                    remain = tmpDo.parse(remain, false);
                }
                if (remain.isEmpty()) {
                    return null;
                }

                TLV permDo = new TLV(TAG_PERM_AR_DO); //DB
                permDo.parse(arDo.value, true);
                permDo.parse(remain, true);
            } else  {
                // Spec requires it must be either TAG_REF_DO or TAG_AR_DO.
                throw new RuntimeException("Invalid Rule type");
+292 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.internal.telephony.uicc;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doAnswer;

import android.content.pm.Signature;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.internal.telephony.TelephonyTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {
    private UiccCarrierPrivilegeRules mUiccCarrierPrivilegeRules;
    public UiccCarrierPrivilegeRulesTest() {
        super();
    }
    private UiccCarrierPrivilegeRulesHandlerThread mTestHandlerThread;
    private Handler mHandler;

    private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 1;
    private static final int EVENT_TEST_DONE = 2;

    @Mock
    private UiccCard mUiccCard;

    private class UiccCarrierPrivilegeRulesHandlerThread extends HandlerThread {

        private UiccCarrierPrivilegeRulesHandlerThread(String name) {
            super(name);
        }

        @Override
        public void onLooperPrepared() {
            /* create a custom handler for the Handler Thread */
            mHandler = new Handler(mTestHandlerThread.getLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
                            /* Upon handling this event, new CarrierPrivilegeRule
                            will be created with the looper of HandlerThread */
                            mUiccCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(
                                    mUiccCard, mHandler.obtainMessage(EVENT_TEST_DONE));
                            break;
                        case EVENT_TEST_DONE:
                            setReady(true);
                            break;
                        default:
                            logd("Unknown Event " + msg.what);
                    }
                }
            };
            setReady(true);
        }
    }

    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
        mTestHandlerThread = new UiccCarrierPrivilegeRulesHandlerThread(TAG);
        mTestHandlerThread.start();

        waitUntilReady();
    }

    @After
    public void tearDown() throws Exception {
        mTestHandlerThread.quit();
        super.tearDown();
        mUiccCarrierPrivilegeRules = null;
    }

    private void testHelper(String hexString) {
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[2];
                AsyncResult ar = new AsyncResult(null, new int[]{0}, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccCard).iccOpenLogicalChannel(anyString(), anyInt(), any(Message.class));

        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(hexString));
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccCard).iccTransmitApduLogicalChannel(anyInt(), anyInt(), anyInt(), anyInt(),
                anyInt(), anyInt(), anyString(), any(Message.class));


        Message mCardOpenLogicalChannel = mHandler.obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE);
        setReady(false);
        mCardOpenLogicalChannel.sendToTarget();
        waitUntilReady();
    }

    @Test
    @SmallTest
    public void testHandleMessage_Normal() {
        /**
         * FF40 45
         *   E2 43
         *      E1 35
         *         C1 14 ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4
         *         CA 1D 636F6D2E676F6F676C652E616E64726F69642E617070732E6D79617070
         *      E3 0A
         *         DB 08 0000000000000001
         */
        final String hexString =
                "FF4045E243E135C114ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4CA1D636F6D2E676F6F676"
                        + "C652E616E64726F69642E617070732E6D79617070E30ADB080000000000000001";

        testHelper(hexString);

        assertTrue(mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
        assertEquals(1, mUiccCarrierPrivilegeRules.getPackageNames().size());
        assertEquals("com.google.android.apps.myapp",
                mUiccCarrierPrivilegeRules.getPackageNames().get(0));
        Signature signature = new Signature("abcd92cbb156b280fa4e1429a6eceeb6e5c1bfe4");
        assertEquals(0, mUiccCarrierPrivilegeRules.getCarrierPrivilegeStatus(signature,
                mUiccCarrierPrivilegeRules.getPackageNames().get(0)));
    }

    @Test
    @SmallTest
    public void testHandleMessage_With4FD0D1() {
        /**
         * FF40 34
         *   E2 32
         *      E1 1E
         *         4F 06 FF FF FF FF FF FF
         *         C1 14 B6 1B E3 4A D2 C2 0D 7A FE D8 49 3C 31 3A 13 7F 89 FA 27 65
         *      E3 10
         *         D0 01 01
         *         D1 01 01
         *         DB 08 00 00 00 00 00 00 00 01
         */
        final String hexString = "FF4034E232E11E4F06FFFFFFFFFFFFC114B61BE34AD2C20D7AFED84"
                + "93C313A137F89FA2765E310D00101D10101DB080000000000000001";

        testHelper(hexString);

        assertTrue(mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
        assertEquals(0, mUiccCarrierPrivilegeRules.getPackageNames().size());
    }

    @Test
    @SmallTest
    public void testHandleMessage_With4FD0() {
        /**
         * FF40 31
         *   E2 2F
         *      E1 1E
         *         4F 06 FF FF FF FF FF FF
         *         C1 14 B6 1B E3 4A D2 C2 0D 7A FE D8 49 3C 31 3A 13 7F 89 FA 27 65
         *      E3 0D
         *         D0 01 01
         *         DB 08 00 00 00 00 00 00 00 01
         */
        final String hexString = "FF4031E22FE11E4F06FFFFFFFFFFFFC114B61BE34AD2C20D7AFED8493C313A"
                + "137F89FA2765E30DD00101DB080000000000000001";

        testHelper(hexString);

        assertTrue(mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
        assertEquals(0, mUiccCarrierPrivilegeRules.getPackageNames().size());
    }

    @Test
    @SmallTest
    public void testHandleMessage_TwoMessages() {
        /**
         * FF40 68
         *   E2 39
         *      E1 2B
         *         4F 06 FFFFFFFFFFFF
         *         C1 02 B61B
         *         CA 1D 636F6D2E676F6F676C652E616E64726F69642E617070732E6D79617070
         *      E3 0A
         *         D0 01 01
         *         D1 01 01
         *         DB 02 0001
         *   E2 2B
         *      E1 23
         *         C1 02 ABCD
         *         CA 1D 636F6D2E676F6F676C652E616E64726F69642E617070732E6D79617070
         *      E3 04
         *         DB 02 0001
         */
        final String hexString =
                "FF4068E239E12B4F06FFFFFFFFFFFFC102B61BCA1D636F6D2E676F6F676C652E616E64726F69642"
                        + "E617070732E6D79617070E30AD00101D10101DB020001E22BE123C102ABCDCA1D636F"
                        + "6D2E676F6F676C652E616E64726F69642E617070732E6D79617070E304DB020001";

        testHelper(hexString);

        assertTrue(mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
        assertEquals(2, mUiccCarrierPrivilegeRules.getPackageNames().size());
        assertEquals("com.google.android.apps.myapp",
                mUiccCarrierPrivilegeRules.getPackageNames().get(0));
        Signature signature1 = new Signature("b61b");
        assertEquals(0, mUiccCarrierPrivilegeRules.getCarrierPrivilegeStatus(signature1,
                mUiccCarrierPrivilegeRules.getPackageNames().get(0)));

        assertEquals("com.google.android.apps.myapp",
                mUiccCarrierPrivilegeRules.getPackageNames().get(1));
        Signature signature2 = new Signature("abcd");
        assertEquals(0, mUiccCarrierPrivilegeRules.getCarrierPrivilegeStatus(signature2,
                mUiccCarrierPrivilegeRules.getPackageNames().get(0)));
    }

    @Test
    @SmallTest
    public void testHandleMessage_InvalidRulesWith4F00() {
        /**
         * FF40 24
         *   E2 22
         *      E1 18
         *         4F 00
         *         C1 14 75C073AFD219AEB221948E828F066E778ADFDF23
         *      E3 06
         *         D0 01 01
         *         D1 01 01
         */
        final String hexString = "FF4024E222E1184F00C11475C073AFD219AEB221948E828F066E778ADFDF23"
                + "E306D00101D10101";

        testHelper(hexString);

        assertTrue(!mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
        assertEquals(0, mUiccCarrierPrivilegeRules.getPackageNames().size());
    }

    @Test
    @SmallTest
    public void testHandleMessage_InvalidRulesWithoutDB() {
        /**
         * FF40 2A
         *   E2 28
         *      E1 1E
         *         4F 06 FF FF FF FF FF FF
         *         C1 14 B6 1B E3 4A D2 C2 0D 7A FE D8 49 3C 31 3A 13 7F 89 FA 27 65
         *      E3 06
         *         D0 01 01
         *         D1 01 01
         */
        final String hexString = "FF402AE228E11E4F06FFFFFFFFFFFFC114B61BE34AD2C20D7AFED8493C313A"
                + "137F89FA2765E306D00101D10101";

        testHelper(hexString);

        assertTrue(!mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
        assertEquals(0, mUiccCarrierPrivilegeRules.getPackageNames().size());
    }
}