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

Commit 3f75a43f authored by Holly Jiuyu Sun's avatar Holly Jiuyu Sun
Browse files

Add Asn1 to uicc/euicc.

Asn1 is the dependency of EuiccCard.
Note: In Patchset 1, all the files are copied from LPA without any
changes. So the diff can be shown against Patchset 1.

Bug: 38206971
Test: unit test
Change-Id: I95d437be26f4965f0ee8ccb8e343fcc601666a6e
Merged-In: I4034858743ffc0225b1dfe59403a7cebcb46f03b
parent 822d1fd0
Loading
Loading
Loading
Loading
+280 −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.euicc.asn1;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.test.suitebuilder.annotation.SmallTest;

import com.android.internal.telephony.uicc.asn1.Asn1Decoder;
import com.android.internal.telephony.uicc.asn1.Asn1Node;
import com.android.internal.telephony.uicc.asn1.InvalidAsn1DataException;
import com.android.internal.telephony.uicc.asn1.TagNotFoundException;

import org.junit.Test;

public class Asn1DecoderTest {

    @SmallTest
    @Test
    public void testNormalOperation() throws TagNotFoundException, InvalidAsn1DataException {
        String hex = "e30c5a0a98102100000000000000";
        Asn1Decoder decoder = new Asn1Decoder(hex);
        assertEquals(0, decoder.getPosition());

        assertTrue(decoder.hasNextNode());
        Asn1Node root = decoder.nextNode();
        assertEquals(hex.length() / 2, decoder.getPosition());
        assertTrue(root.isConstructed());
        assertEquals(0xE3, root.getTag());
        assertEquals(0x0E, root.getEncodedLength());
        assertFalse(root.hasValue());

        Asn1Node node = root.getChild(0x5A);
        assertEquals(1, root.getChildren().size());
        assertEquals(1, root.getChildren(0x5A).size());
        assertEquals(node, root.getChildren().get(0));
        assertEquals(node, root.getChildren(0x5A).get(0));
        assertFalse(node.isConstructed());
        assertEquals(0x5A, node.getTag());
        assertEquals(0x0C, node.getEncodedLength());
        assertTrue(node.hasValue());
        assertArrayEquals(
                new byte[] {(byte) 0x98, 0x10, 0x21, 0, 0, 0, 0, 0, 0, 0}, node.asBytes());

        assertFalse(decoder.hasNextNode());
        assertEquals(hex.length() / 2, decoder.getPosition());
    }

    @SmallTest
    @Test
    public void testHighTagNumberForm() throws TagNotFoundException, InvalidAsn1DataException {
        String hex = "bf370c5a0a98102100000000000000";
        Asn1Decoder decoder = new Asn1Decoder(hex);

        assertTrue(decoder.hasNextNode());
        Asn1Node root = decoder.nextNode();
        assertTrue(root.isConstructed());
        assertEquals(0xBF37, root.getTag());
        assertEquals(0x0F, root.getEncodedLength());
        assertTrue(root.isConstructed());

        Asn1Node node = root.getChild(0x5A);
        assertEquals(0x0C, node.getEncodedLength());
    }

    @SmallTest
    @Test
    public void testNodeList() throws TagNotFoundException, InvalidAsn1DataException {
        String hex = "e30c5a0a98102100000000000000e30c5a0a98102100000000000001";

        Asn1Decoder decoder = new Asn1Decoder(hex);
        assertEquals(0, decoder.getPosition());

        assertTrue(decoder.hasNextNode());
        Asn1Node firstRoot = decoder.nextNode();
        assertEquals(hex.length() / 4, decoder.getPosition());
        assertTrue(firstRoot.isConstructed());
        assertEquals(0xE3, firstRoot.getTag());
        Asn1Node childOfFirst = firstRoot.getChild(0x5A);
        assertNotNull(childOfFirst);
        assertFalse(childOfFirst.isConstructed());
        assertEquals(0x5A, childOfFirst.getTag());
        assertTrue(childOfFirst.hasValue());
        assertArrayEquals(
                new byte[] {(byte) 0x98, 0x10, 0x21, 0, 0, 0, 0, 0, 0, 0}, childOfFirst.asBytes());

        assertTrue(decoder.hasNextNode());
        Asn1Node secondRoot = decoder.nextNode();
        assertEquals(hex.length() / 2, decoder.getPosition());
        assertTrue(secondRoot.isConstructed());
        assertEquals(0xE3, secondRoot.getTag());
        Asn1Node childOfSecond = secondRoot.getChild(0x5A);
        assertNotNull(childOfSecond);
        assertFalse(childOfSecond.isConstructed());
        assertEquals(0x5A, childOfSecond.getTag());
        assertTrue(childOfSecond.hasValue());
        assertArrayEquals(
                new byte[] {(byte) 0x98, 0x10, 0x21, 0, 0, 0, 0, 0, 0, 1}, childOfSecond.asBytes());

        assertFalse(decoder.hasNextNode());
        assertEquals(hex.length() / 2, decoder.getPosition());
    }

    @SmallTest
    @Test
    public void testMissingData() throws TagNotFoundException, InvalidAsn1DataException {
        String hex = "e30c5a0a98102100000000000000e30c5a0a98102100000000";
        Asn1Decoder decoder = new Asn1Decoder(hex);
        assertEquals(0, decoder.getPosition());

        assertTrue(decoder.hasNextNode());
        Asn1Node firstRoot = decoder.nextNode();
        assertEquals(0x0E, decoder.getPosition());
        assertTrue(firstRoot.isConstructed());
        assertEquals(0xE3, firstRoot.getTag());
        Asn1Node childOfFirst = firstRoot.getChild(0x5A);
        assertNotNull(childOfFirst);
        assertFalse(childOfFirst.isConstructed());
        assertEquals(0x5A, childOfFirst.getTag());
        assertTrue(childOfFirst.hasValue());
        assertArrayEquals(
                new byte[] {(byte) 0x98, 0x10, 0x21, 0, 0, 0, 0, 0, 0, 0}, childOfFirst.asBytes());

        assertTrue(decoder.hasNextNode());
        try {
            decoder.nextNode();
            fail("Bytes should not be parsed.");
        } catch (InvalidAsn1DataException e) {
            assertEquals(0xE3, e.getTag());
        }
    }

    @SmallTest
    @Test
    public void testEmptyData() throws TagNotFoundException, InvalidAsn1DataException {
        String hex = "e3025a00e3025a00";
        Asn1Decoder decoder = new Asn1Decoder(hex);
        assertEquals(0, decoder.getPosition());

        assertTrue(decoder.hasNextNode());
        Asn1Node firstRoot = decoder.nextNode();
        assertEquals(hex.length() / 4, decoder.getPosition());
        assertTrue(firstRoot.isConstructed());
        assertEquals(0xE3, firstRoot.getTag());
        Asn1Node childOfFirst = firstRoot.getChild(0x5A);
        assertNotNull(childOfFirst);
        assertFalse(childOfFirst.isConstructed());
        assertEquals(0x5A, childOfFirst.getTag());
        assertTrue(childOfFirst.hasValue());
        assertArrayEquals(new byte[] {}, childOfFirst.asBytes());

        assertTrue(decoder.hasNextNode());
        Asn1Node secondRoot = decoder.nextNode();
        assertEquals(hex.length() / 2, decoder.getPosition());
        assertTrue(secondRoot.isConstructed());
        assertEquals(0xE3, secondRoot.getTag());
        Asn1Node childOfSecond = secondRoot.getChild(0x5A);
        assertNotNull(childOfSecond);
        assertFalse(childOfSecond.isConstructed());
        assertEquals(0x5A, childOfSecond.getTag());
        assertTrue(childOfSecond.hasValue());
        assertArrayEquals(new byte[] {}, childOfSecond.asBytes());

        assertFalse(decoder.hasNextNode());
        assertEquals(hex.length() / 2, decoder.getPosition());
    }

    @SmallTest
    @Test
    public void testLongFormLength() throws TagNotFoundException, InvalidAsn1DataException {
        String hex = "bf37075a820003010203";
        Asn1Decoder decoder = new Asn1Decoder(hex);

        assertTrue(decoder.hasNextNode());
        Asn1Node root = decoder.nextNode();
        assertTrue(root.isConstructed());
        assertEquals(0xBF37, root.getTag());
        assertEquals(10, root.getEncodedLength());
        assertTrue(root.isConstructed());

        Asn1Node node = root.getChild(0x5A);
        assertEquals(5, node.getEncodedLength());
        assertArrayEquals(new byte[] {1, 2, 3}, node.asBytes());
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testDecodeEmptyByteArray() throws TagNotFoundException, InvalidAsn1DataException {
        new Asn1Decoder("").nextNode();
    }

    @SmallTest
    @Test(expected = IndexOutOfBoundsException.class)
    public void testDecodeIndexOutOfBounds() throws TagNotFoundException, InvalidAsn1DataException {
        new Asn1Decoder(new byte[] {1, 2}, 0, 3);
    }

    @SmallTest
    @Test(expected = InvalidAsn1DataException.class)
    public void testIncompleteLength() throws TagNotFoundException, InvalidAsn1DataException {
        try {
            new Asn1Decoder("BF37").nextNode();
        } catch (InvalidAsn1DataException e) {
            assertEquals(0, e.getTag());
            assertEquals("Invalid length at position: 2 (tag=0)", e.getMessage());
            throw e;
        }
    }

    @SmallTest
    @Test(expected = InvalidAsn1DataException.class)
    public void testInvalidTag() throws TagNotFoundException, InvalidAsn1DataException {
        try {
            new Asn1Decoder("BF818283840100").nextNode();
        } catch (InvalidAsn1DataException e) {
            assertEquals(0, e.getTag());
            assertEquals("Cannot parse tag at position: 0 (tag=0)", e.getMessage());
            throw e;
        }
    }

    @SmallTest
    @Test(expected = InvalidAsn1DataException.class)
    public void testIncompleteData() throws TagNotFoundException, InvalidAsn1DataException {
        try {
            new Asn1Decoder("BF81010200").nextNode();
        } catch (InvalidAsn1DataException e) {
            assertEquals(0xBF8101, e.getTag());
            assertEquals(
                    "Incomplete data at position: 4, expected bytes: 2, "
                            + "actual bytes: 1 (tag=12550401)",
                    e.getMessage());
            throw e;
        }
    }

    @SmallTest
    @Test(expected = InvalidAsn1DataException.class)
    public void testIncompleteLongFormLength()
            throws TagNotFoundException, InvalidAsn1DataException {
        try {
            new Asn1Decoder("BF81018200").nextNode();
        } catch (InvalidAsn1DataException e) {
            assertEquals(0xBF8101, e.getTag());
            assertEquals("Cannot parse length at position: 4 (tag=12550401)", e.getMessage());
            throw e;
        }
    }

    @SmallTest
    @Test(expected = InvalidAsn1DataException.class)
    public void testInvalidLongFormLength() throws TagNotFoundException, InvalidAsn1DataException {
        try {
            new Asn1Decoder("BF8101851234567890").nextNode();
        } catch (InvalidAsn1DataException e) {
            assertEquals(0xBF8101, e.getTag());
            assertEquals("Cannot parse length at position: 4 (tag=12550401)", e.getMessage());
            throw e;
        }
    }
}
+303 −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.euicc.asn1;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.test.suitebuilder.annotation.SmallTest;

import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.asn1.Asn1Decoder;
import com.android.internal.telephony.uicc.asn1.Asn1Node;
import com.android.internal.telephony.uicc.asn1.InvalidAsn1DataException;
import com.android.internal.telephony.uicc.asn1.TagNotFoundException;

import org.junit.Test;

public class Asn1NodeTest {

    @SmallTest
    @Test
    public void testCreateConstructedNodeWithShortTag() {
        Asn1Node node = Asn1Node.newBuilder(0x65).build();
        assertEquals(0x65, node.getTag());
        assertTrue(node.isConstructed());
        assertEquals(2, node.getEncodedLength());
        assertEquals(0, node.getDataLength());
        assertArrayEquals(new byte[] {0x65, 0x00}, node.toBytes());
    }

    @SmallTest
    @Test
    public void testCreateConstructedNodeWithLongTag() {
        Asn1Node node = Asn1Node.newBuilder(0x3F34).build();
        assertEquals(0x3F34, node.getTag());
        assertTrue(node.isConstructed());
        assertEquals(3, node.getEncodedLength());
        assertEquals(0, node.getDataLength());
        assertArrayEquals(new byte[] {0x3F, 0x34, 0x00}, node.toBytes());
    }

    @SmallTest
    @Test
    public void testChildren() throws TagNotFoundException, InvalidAsn1DataException {
        Asn1Node node =
                Asn1Node.newBuilder(0x3F34)
                        .addChild(Asn1Node.newBuilder(0x35).addChild(Asn1Node.newBuilder(0x36)))
                        .addChild(Asn1Node.newBuilder(0x35))
                        .addChild(Asn1Node.newBuilder(0x37))
                        .build();

        assertEquals(0x3F34, node.getTag());
        assertEquals(3, node.getChildren().size());
        assertEquals(0x35, node.getChildren().get(0).getTag());
        assertEquals(0x35, node.getChildren().get(1).getTag());
        assertEquals(0x37, node.getChildren().get(2).getTag());
        assertEquals(2, node.getChildren(0x35).size());
        assertEquals(0x35, node.getChildren(0x35).get(0).getTag());
        assertEquals(0x35, node.getChildren(0x35).get(1).getTag());
        assertEquals(1, node.getChild(0x35).getChildren().size());
        assertEquals(0, node.getChildren().get(1).getChildren().size());
        assertEquals(0x36, node.getChild(0x35).getChildren().get(0).getTag());

        assertTrue(node.hasChild(0x35, 0x36));
        assertFalse(node.hasChild(0x38, 0x39));
        assertTrue(node.getChild(0x35).hasChild(0x36));
        assertFalse(node.getChild(0x35).hasChild(0x39));
    }

    @SmallTest
    @Test
    public void testNonExitingChildren() throws TagNotFoundException, InvalidAsn1DataException {
        Asn1Node node =
                Asn1Node.newBuilder(0x3F34)
                        .addChild(Asn1Node.newBuilder(0x34))
                        .addChild(Asn1Node.newBuilder(0x35).addChild(Asn1Node.newBuilder(0x36)))
                        .addChildAsInteger(0x11, 123)
                        .build();

        assertEquals(0, node.getChild(0x34).getChildren(0x37).size());
        assertEquals(0, node.getChildren(0x37).size());
        assertEquals(0, node.getChild(0x11).getChildren(0x37).size());
        assertEquals(0, node.getChild(0x11).getChildren().size());
        try {
            node.getChild(0x35).getChild(0x37);
            fail("0x37 should not exist.");
        } catch (TagNotFoundException e) {
            assertEquals(0x37, e.getTag());
        }
        try {
            node.getChild(0x35, 0x37);
            fail("0x37 should not exist.");
        } catch (TagNotFoundException e) {
            assertEquals(0x37, e.getTag());
        }
        try {
            node.getChild(0x11).getChild(0x37);
            fail("0x37 should not exist.");
        } catch (TagNotFoundException e) {
            assertEquals(0x37, e.getTag());
        }
    }

    @SmallTest
    @Test
    public void testBuilderAndGetters() throws TagNotFoundException, InvalidAsn1DataException {
        Asn1Node node =
                Asn1Node.newBuilder(0x30)
                        .addChildAsInteger(0x11, 1234567)
                        .addChildAsString(0x12, "This is a test.")
                        .addChild(
                                Asn1Node.newBuilder(0x31)
                                        .addChildAsBits(0x13, 0xF2344)
                                        .addChildAsBytes(0x14, new byte[] {-1, 0, -1}))
                        .addChildAsBoolean(0x15, true)
                        .addChildAsBoolean(0x16, false)
                        .addChildren(IccUtils.hexStringToBytes("13040422C4F01403FF00FF"))
                        .build();

        assertEquals(54, node.getEncodedLength());
        assertEquals(52, node.getDataLength());

        final String nodeHex =
                "3034110312D687120F54686973206973206120746573742E310B13040422C4F0"
                        + "1403FF00FF1501FF16010013040422C4F01403FF00FF";
        assertEquals(nodeHex, node.toHex());
        assertEquals("3034", node.getHeadAsHex());
        assertEquals(1234567, node.getChild(0x11).asInteger());
        assertEquals("This is a test.", node.getChild(0x12).asString());
        assertEquals(0xF2344, node.getChild(0x31).getChild(0x13).asBits());
        assertArrayEquals(new byte[] {-1, 0, -1}, node.getChild(0x31).getChild(0x14).asBytes());
        assertTrue(node.getChild(0x15).asBoolean());
        assertFalse(node.getChild(0x16).asBoolean());
        assertEquals(0xF2344, node.getChild(0x13).asBits());
        assertArrayEquals(new byte[] {-1, 0, -1}, node.getChild(0x14).asBytes());
    }

    @SmallTest
    @Test
    public void testGettersInvalidData() throws TagNotFoundException, InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0x30).addChildAsString(0x12, "string").build();
        try {
            node.getChild(0x12).asInteger();
            fail("Should not be parsed.");
        } catch (InvalidAsn1DataException e) {
            assertEquals(0x12, e.getTag());
        }
        try {
            node.getChild(0x12).asBits();
            fail("Should not be parsed.");
        } catch (InvalidAsn1DataException e) {
            assertEquals(0x12, e.getTag());
        }
        try {
            node.getChild(0x12).asBoolean();
            fail("Should not be parsed.");
        } catch (InvalidAsn1DataException e) {
            assertEquals(0x12, e.getTag());
        }
    }

    @SmallTest
    @Test
    public void testWriteToBytes() throws InvalidAsn1DataException {
        final String nodeHex =
                "3031110312D687120F54686973206973206120746573742E310B13040422C4F0"
                        + "1403FF00FF1501FF13040422C4F01403FF00FF";

        Asn1Node node = new Asn1Decoder(nodeHex).nextNode();
        // Writes the bytes before children accessed.
        assertEquals(nodeHex, node.toHex());
        // Writes the bytes after children accessed.
        node.getChildren();
        assertEquals(nodeHex, node.toHex());
    }

    @SmallTest
    @Test
    public void testLongFormLength() throws TagNotFoundException, InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).addChildAsBytes(0x5A, new byte[257]).build();
        assertEquals(266, node.getEncodedLength());
        assertEquals(261, node.getDataLength());
        assertEquals(257, node.getChild(0x5A).getDataLength());
        assertEquals("BF37820105", node.getHeadAsHex());

        byte[] expected = new byte[266];
        System.arraycopy(IccUtils.hexStringToBytes("BF378201055A820101"), 0, expected, 0, 9);
        byte[] actual = new byte[266];
        node.writeToBytes(actual, 0);
        assertArrayEquals(expected, actual);
    }

    @SmallTest
    @Test(expected = IllegalArgumentException.class)
    public void testBuilder_NonConstructedTag() {
        Asn1Node.newBuilder(0x87);
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testBuilderAddChildAsInteger_ConstructedTag() {
        Asn1Node.newBuilder(0xBF37).addChildAsInteger(0xBF37, 1);
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testBuilderAddChildAsString_ConstructedTag() {
        Asn1Node.newBuilder(0xBF37).addChildAsString(0xBF37, "");
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testBuilderAddChildAsBytes_ConstructedTag() {
        Asn1Node.newBuilder(0xBF37).addChildAsBytesFromHex(0xBF37, "00");
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testBuilderAddChildAsBits_ConstructedTag() {
        Asn1Node.newBuilder(0xBF37).addChildAsBits(0xBF37, 1);
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testBuilderAddChildAsBoolean_ConstructedTag() {
        Asn1Node.newBuilder(0xBF37).addChildAsBoolean(0xBF37, true);
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testAsInteger_ConstructedTag() throws InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
        node.asInteger();
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testAsLong_ConstructedTag() throws InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
        node.asRawLong();
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testAsString_ConstructedTag() throws InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
        node.asString();
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testAsBytes_ConstructedTag() throws InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
        node.asBytes();
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testAsBits_ConstructedTag() throws InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
        node.asBits();
    }

    @SmallTest
    @Test(expected = IllegalStateException.class)
    public void testAsBoolean_ConstructedTag() throws InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
        node.asBoolean();
    }

    @SmallTest
    @Test(expected = InvalidAsn1DataException.class)
    public void testAsBoolean_InvalidData() throws TagNotFoundException, InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).addChildAsString(1, "1").build();
        node.getChild(1).asBoolean();
    }

    @SmallTest
    @Test(expected = IndexOutOfBoundsException.class)
    public void testWriteToBytes_IndexOutOfBounds()
            throws TagNotFoundException, InvalidAsn1DataException {
        Asn1Node node = Asn1Node.newBuilder(0xBF37).addChildAsString(1, "1").build();
        byte[] bytes = new byte[1];
        node.writeToBytes(bytes, 0);
    }
}
+244 −0

File added.

Preview size limit exceeded, changes collapsed.