/**************************************************************************** * Copyright (C) 2012 ecsec GmbH. * All rights reserved. * Contact: ecsec GmbH (info@ecsec.de) * * This file is part of the Open eCard App. * * GNU General Public License Usage * This file may be used under the terms of the GNU General Public * License version 3.0 as published by the Free Software Foundation * and appearing in the file LICENSE.GPL included in the packaging of * this file. Please review the following information to ensure the * GNU General Public License version 3.0 requirements will be met: * http://www.gnu.org/copyleft/gpl.html. * * Other Usage * Alternatively, this file may be used in accordance with the terms * and conditions contained in a signed written agreement between * you and ecsec GmbH. * ***************************************************************************/ package org.openecard.common.apdu.common; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Random; import org.openecard.common.apdu.GeneralAuthenticate; import org.openecard.common.apdu.ReadBinary; import org.openecard.common.util.ByteUtils; import org.openecard.common.util.IntegerUtils; import org.testng.Assert; import org.testng.annotations.Test; import static org.testng.Assert.*; /** * @author Moritz Horsch <horsch@cdc.informatik.tu-darmstadt.de> */ public class CardCommandAPDUTest { Random rnd = new Random(); @Test public void testLengthCommand() throws IOException { CardCommandAPDU apdu = new CardCommandAPDU((byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF); assertEquals(apdu.toByteArray(), new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF}); apdu = new CardCommandAPDU((byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, fillBytes(1)); assertEquals(apdu.getLC(), 1); apdu = new CardCommandAPDU((byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, fillBytes(255)); assertEquals(apdu.getLC(), 255); apdu = new CardCommandAPDU((byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, fillBytes(256)); assertEquals(apdu.getLC(), 256); apdu = new CardCommandAPDU((byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, fillBytes(65535)); assertEquals(apdu.getLC(), 65535); } @Test public void testLengthExpected() throws IOException { CardCommandAPDU apdu = new ReadBinary(); assertEquals(apdu.toByteArray(), new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF}); apdu.setLE(1); assertEquals(apdu.toByteArray(), new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, (byte) 0x01}); apdu.setLE(255); assertEquals(apdu.toByteArray(), new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}); apdu.setLE(256); assertEquals(apdu.toByteArray(), new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, (byte) 0x00}); apdu.setLE(257); assertEquals(apdu.toByteArray(), new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, (byte) 0x00, (byte) 0x01, (byte) 0x01}); apdu.setLE(65535); assertEquals(apdu.toByteArray(), new byte[]{(byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}); apdu = new CardCommandAPDU((byte) 0x00, (byte) 0xB0, (byte) 0x00, (byte) 0xFF, fillBytes(65535)); apdu.setLE(65535); assertEquals(apdu.getLC(), 65535); assertEquals(apdu.getLE(), 65535); // test an expected length of 256 with an extended length command apdu // the expected LE is {0x01, 0x00} apdu.setLE(256); int length = apdu.toByteArray().length; assertEquals(apdu.toByteArray()[length-2], 0x01); assertEquals(apdu.toByteArray()[length-1], 0x00); } @Test public void testBodyParsing() throws IOException { CardCommandAPDU apdu = new ReadBinary(); // Case 2. : |CLA|INS|P1|P2|LE| apdu.setBody(new byte[]{(byte) 0xFF}); assertEquals(apdu.getLE(), 255); assertEquals(apdu.getLC(), -1); assertNull(apdu.getData()); // Case 2.1: |CLA|INS|P1|P2|EXTLE| apdu.setBody(new byte[]{(byte) 0x00, (byte) 0x01, (byte) 0xFF}); assertEquals(apdu.getLC(), -1); assertEquals(apdu.getLE(), 511); assertNull(apdu.getData()); // Case 3. : |CLA|INS|P1|P2|LC|DATA| apdu.setBody(fillBytesWithLength(240)); assertEquals(apdu.getLC(), 240); assertEquals(apdu.getLE(), -1); // Case 3.1: |CLA|INS|P1|P2|EXTLC|DATA| apdu.setBody(fillBytesWithLength(366)); assertEquals(apdu.getLC(), 366); assertEquals(apdu.getLE(), -1); // Case 4. : |CLA|INS|P1|P2|LC|DATA|LE apdu.setBody(new byte[]{(byte) 0x01, (byte) 0x01, (byte) 0xFF}); assertEquals(apdu.getLE(), 255); assertEquals(apdu.getLC(), 1); // Case 4.1 : |CLA|INS|P1|P2|EXTLC|DATA|LE| apdu.setBody(ByteUtils.concatenate(fillBytesWithLength(366), (byte) 0xF0)); assertEquals(apdu.getLE(), 240); assertEquals(apdu.getLC(), 366); // Case 4.2 : |CLA|INS|P1|P2|LC|DATA|EXTLE| apdu.setBody(new byte[]{(byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xFF}); assertEquals(apdu.getLE(), 511); assertEquals(apdu.getLC(), 1); // Case 4.3: |CLA|INS|P1|P2|EXTLC|DATA|EXTLE| apdu.setBody(ByteUtils.concatenate(fillBytesWithLength(366), new byte[]{(byte) 0x00, (byte) 0x01, (byte) 0xFF})); assertEquals(apdu.getLE(), 511); assertEquals(apdu.getLC(), 366); } @Test public void testAPDUs() { CardCommandAPDU apdu = new GeneralAuthenticate(); } @Test public void testConstructors() { // test constructor CardCommandAPDU(byte[] commandAPDU) with Case 4.2 APDU CardCommandAPDU capdu = new CardCommandAPDU(new byte[]{(byte) 0x00, (byte) 0xAB, (byte) 0xBC, (byte) 0xDE, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xFF}); assertEquals((byte) 0x00, capdu.getCLA()); assertEquals((byte) 0xAB, capdu.getINS()); assertEquals((byte) 0xBC, capdu.getP1()); assertEquals((byte) 0xDE, capdu.getP2()); assertEquals((byte) 0x01, capdu.getLC()); assertEquals(511, capdu.getLE()); assertEquals(new byte[]{(byte) 0x01}, capdu.getData()); assertEquals(new byte[]{(byte) 0x00, (byte) 0xAB, (byte) 0xBC, (byte) 0xDE}, capdu.getHeader()); // test constructor CardCommandAPDU(byte[] commandAPDU) with Case 1 APDU capdu = new CardCommandAPDU(new byte[]{(byte) 0x00, (byte) 0xAB, (byte) 0xBC, (byte) 0xDE}); assertEquals((byte) 0x00, capdu.getCLA()); assertEquals((byte) 0xAB, capdu.getINS()); assertEquals((byte) 0xBC, capdu.getP1()); assertEquals((byte) 0xDE, capdu.getP2()); assertEquals(-1, capdu.getLC()); assertEquals(-1, capdu.getLE()); assertNull(capdu.getData()); assertEquals(new byte[]{(byte) 0x00, (byte) 0xAB, (byte) 0xBC, (byte) 0xDE}, capdu.getHeader()); } @Test public void testGetBody() { byte[] apdu = new byte[]{(byte) 0x00, (byte) 0xAB, (byte) 0xBC, (byte) 0xDE, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xFF}; Assert.assertEquals(CardCommandAPDU.getBody(apdu), new byte[]{(byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xFF}); } @Test public void testGetHeader() { byte[] apdu = new byte[]{(byte) 0x00, (byte) 0xAB, (byte) 0xBC, (byte) 0xDE, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xFF}; Assert.assertEquals(CardCommandAPDU.getHeader(apdu), new byte[]{(byte) 0x00, (byte) 0xAB, (byte) 0xBC, (byte) 0xDE}); } @Test(expectedExceptions = IllegalArgumentException.class) public void testGetHeader2() { byte[] apdu = new byte[]{(byte) 0x00, (byte) 0xAB, (byte) 0xBC}; CardCommandAPDU.getHeader(apdu); } private byte[] fillBytesWithLength(int i) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); if (i > 255) { baos.write((byte) 0x00); } baos.write(IntegerUtils.toByteArray(i)); for (int j = 0; j < i; j++) { baos.write((byte) (rnd.nextInt() & (byte) 0xFF)); } return baos.toByteArray(); } private byte[] fillBytes(int i) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); for (int j = 0; j < i; j++) { baos.write((byte) (rnd.nextInt() & (byte) 0xFF)); } return baos.toByteArray(); } }