/**************************************************************************** * 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.util; import iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType; import iso.std.iso_iec._24727.tech.schema.Transmit; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * * @author Johannes Schmoelz <johannes.schmoelz@ecsec.de> * @author Tobias Wich <tobias.wich@ecsec.de> * @author Dirk Petrautzki <petrautzki@hs-coburg.de> */ @Deprecated public class CardCommands { private static final byte CLASS_BYTE = (byte) 0x00; /** * Remove trailer (aka status bytes) from response APDU. * * @param responseApdu * @return */ public static byte[] getDataFromResponse(byte[] responseApdu) { return Arrays.copyOf(responseApdu, responseApdu.length - 2); } /** * Remove data from response APDU thereby only returning trailer (aka status * bytes). * * @param responseApdu * @return */ public static byte[] getResultFromResponse(byte[] responseApdu) { return Arrays.copyOfRange(responseApdu, responseApdu.length - 2, responseApdu.length); } public static InputAPDUInfoType makeApdu(byte[] cmd, List<byte[]> responses) { InputAPDUInfoType apdu = new InputAPDUInfoType(); apdu.setInputAPDU(cmd); apdu.getAcceptableStatusCode().addAll(responses); return apdu; } public static Transmit makeTransmit(byte[] slotHandle, byte[] cmd, List<byte[]> responses) { Transmit t = new Transmit(); t.setSlotHandle(slotHandle); InputAPDUInfoType apdu = makeApdu(cmd, responses); t.getInputAPDUInfo().add(apdu); return t; } private static byte[] buildContent(byte[] content) { // create lc and make it extended if needed byte[] lc = IntegerUtils.toByteArray(content.length); if (lc.length == 2) { lc = ByteUtils.concatenate((byte) 0, lc); } content = ByteUtils.concatenate(lc, content); return content; } private static byte[] buildLength(short length, byte[] content) { // Le with value 0x00 means maximum length expected if (length == (short) 0) { return new byte[] { 0 }; } // only care about Lc field if there is a content byte[] data; if (content == null && length > (short) 0xFF) { data = new byte[] { 0 }; } else { data = new byte[0]; } if (length > 0xFF) { // Lc + extended length data = ByteUtils.concatenate(data, ShortUtils.toByteArray(length)); return data; } else { // Lc + short length data = ByteUtils.concatenate(data, (byte) length); return data; } } public static byte[] genericCommand(byte cmd, byte[] p12, byte[] content) { byte[] apdu = { CLASS_BYTE, cmd }; apdu = ByteUtils.concatenate(apdu, p12); content = buildContent(content); apdu = ByteUtils.concatenate(apdu, content); return apdu; } public static byte[] genericCommand(byte cmd, byte[] p12, byte[] content, short length) { byte[] apdu = { CLASS_BYTE, cmd }; apdu = ByteUtils.concatenate(apdu, p12); content = buildContent(content); apdu = ByteUtils.concatenate(apdu, content); byte[] lenBytes = buildLength(length, content); apdu = ByteUtils.concatenate(apdu, lenBytes); return apdu; } public static byte[] genericCommand(byte cmd, byte[] p12) { byte[] apdu = { CLASS_BYTE, cmd }; apdu = ByteUtils.concatenate(apdu, p12); return apdu; } public static byte[] genericCommand(byte cmd, byte[] p12, short length) { byte[] apdu = { CLASS_BYTE, cmd }; apdu = ByteUtils.concatenate(apdu, p12); byte[] lenBytes = buildLength(length, null); apdu = ByteUtils.concatenate(apdu, lenBytes); return apdu; } public static byte[] addCommandChaining(byte[] apdu) { apdu[0] |= 0x10; return apdu; } public static class InternalAuthenticate { private static final byte COMMAND_INTERNAL_AUTHENTICATE = (byte) 0x88; /** * Creates an APDU that is equivalent to the command * "INTERNAL AUTHENTICATE". The created APDU is a case 4 short or * extended command APDU. * * @param data * - data which shall be authenticated * @param le * - expected length of answer * @return APDU as byte array */ public static byte[] generic(byte[] data, short le) { return genericCommand(COMMAND_INTERNAL_AUTHENTICATE, new byte[] { 0x00, 0x00 }, data, le); } } public static class Verify { private static final byte COMMAND_VERIFY = (byte) 0x20; /** * Creates an APDU that is equivalent to the command "VERIFY". The * created APDU is a case 3 short command APDU. * * @param p1 * - parameter for data field * @param p2 * - password reference * @param data * - data to be verified * @return APDU as byte array */ public static byte[] generic(byte p1, byte p2, byte[] data) { return genericCommand(COMMAND_VERIFY, new byte[] { p1, p2 }, data); } } public static class GetChallenge { private static final byte COMMAND_GET_CHALLENGE = (byte) 0x84; /** * Creates an APDU that is equivalent to the command "GET CHALLENGE". * The requested challenge will have a size of 8 bytes. The created APDU * is a case 2 short command APDU. * * @return APDU as byte array */ public static byte[] generic() { return genericCommand(COMMAND_GET_CHALLENGE, new byte[] { 0x00, 0x00 }, (short) 0x08); } /** * Creates an APDU that is equivalent to the command "GET CHALLENGE". * The created APDU is a case 2 short command APDU. * * @param le * - size of requested challenge * @return APDU as byte array */ public static byte[] generic(short le) { return genericCommand(COMMAND_GET_CHALLENGE, new byte[] { 0x00, 0x00 }, le); } } public static class ExternalAuthenticate { private static final byte COMMAND_EXTERNAL_AUTHENTICATE = (byte) 0x82; /** * Creates an APDU that is equivalent to the command * "EXTERNAL AUTHENTICATE". Depending on the size of the parameter data, * the created APDU is either a case 3 short command APDU or a case 3 * extended command APDU. * * @param data * - data which originates from an external entity (e.g. * another smart card) * @return APDU as byte array */ public static byte[] generic(byte[] data) { byte[] p12 = new byte[] { (byte) 0x00, (byte) 0x00 }; return genericCommand(COMMAND_EXTERNAL_AUTHENTICATE, p12, data); } } public static class ManageSecurityEnvironment { private static final byte COMMAND_MANAGE_SECURITY_ENVIRONMENT = (byte) 0x22; /** * Creates an APDU that is equivalent to the command * "MSE Set DST". Depending on the size of the parameter data, * the created APDU is either a case 3 short command APDU or a case 3 * extended command APDU. * * @param data * - data which originates from an external entity (e.g. * another smart card) * @return APDU as byte array */ public static byte[] setDST(byte[] data) { byte[] p12 = new byte[] { (byte) 0x81, (byte) 0xB6 }; data = ByteUtils.concatenate(new byte[] { (byte) 0x83, (byte) data.length }, data); return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } public static class setAT { /** * Creates a new MSE:Set AT APDU for PACE. TR-03110 2.05 Section * B.11.1. * * @param oid * Cryptograhic mechanism reference * @param chat * Certificate Holder Authorization Template * @param passwordType type of the password * @return MSE:Set AT APDU */ public static byte[] PACE(byte[] oid, byte passwordType, byte[] chat) { byte[] p12 = new byte[] { (byte) 0xC1, (byte) 0xA4 }; byte[] data = ByteUtils.concatenate(new byte[] { (byte) 0x80, (byte) oid.length }, oid); data = ByteUtils.concatenate(data, new byte[] { (byte) 0x83, 0x01, passwordType }); if (chat != null) { data = ByteUtils.concatenate(data, chat); } return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } /** * Creates a new MSE:Set AT APDU for Terminal Authentication. * TR-03110 2.05 Section B.11.1. * * @param oid * Cryptograhic mechanism reference * @param pkPCD * Ephemeral Public Key PCD * @param chr * Certificate Holder Reference * @param aad * Auxiliary authenticated data * @return MSE:Set AT APDU */ public static byte[] TA(byte[] oid, byte[] chr, byte[] pkPCD, byte[] aad) { byte[] p12 = new byte[] { (byte) 0x81, (byte) 0xA4 }; byte[] data = ByteUtils.concatenate(new byte[] { (byte) 0x80, (byte) oid.length }, oid); if (chr != null) { data = ByteUtils.concatenate(data, ByteUtils.concatenate(new byte[] { (byte) 0x83, (byte) chr.length }, chr)); } if (pkPCD != null) { data = ByteUtils.concatenate(data, ByteUtils.concatenate(new byte[] { (byte) 0x91, (byte) pkPCD.length }, pkPCD)); } if (aad != null) { data = ByteUtils.concatenate(data, aad); } return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } /** * Create a new MSE:Set AT APDU for Chip Authentication. TR-03110 * 2.05 Section B.11.1. * * @param oid * Cryptograhic mechanism reference * @param keyID * Reference of a private key * @return MSE:Set AT APDU */ public static byte[] CA(byte[] oid, byte[] keyID) { byte[] p12 = new byte[] { (byte) 0x41, (byte) 0xA4 }; byte[] data = ByteUtils.concatenate(new byte[] { (byte) 0x80, (byte) oid.length }, oid); if (keyID != null) { keyID = ByteUtils.cutLeadingNullByte(keyID); data = ByteUtils.concatenate(data, ByteUtils.concatenate(new byte[] { (byte) 0x84, (byte) keyID.length }, keyID)); } return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } } /** * Creates an APDU that is equivalent to the command * "MANAGE SECURITY ENVIRONMENT". The command selects a private key for * a following "INTERNAL AUTHENTICATE". The created APDU is a case 3 * short command APDU. * * @param keyRef * - key reference * @param algId * - algorithm identifier * @return APDU as byte array */ @Deprecated public static byte[] mseSelectPrKeyIntAuth(byte keyRef, byte algId) { byte[] p12 = new byte[] { (byte) 0x41, (byte) 0xA4 }; byte[] data = new byte[] { (byte) 0x84, (byte) 0x01, keyRef, (byte) 0x80, (byte) 0x01, algId }; return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } @Deprecated public static byte[] mseSelectPrKeySignature(byte keyRef, byte algId) { byte[] p12 = new byte[] { (byte) 0x41, (byte) 0xB6 }; byte[] data = new byte[] { (byte) 0x84, (byte) 0x01, keyRef, (byte) 0x80, (byte) 0x01, algId }; return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } @Deprecated public static byte[] mseSelectPrKeyDecipher(byte keyRef, byte algId){ byte[] p12 = new byte[] { (byte) 0x41, (byte) 0xB8 }; byte[] data = new byte[] { (byte) 0x84, (byte) 0x01, keyRef, (byte) 0x80, (byte) 0x01, algId }; return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } /** * Creates an APDU that is equivalent to the command * "MANAGE SECURITY ENVIRONMENT". The command selects a public key for * the verification of a card verifiable certificate (CVC). The created * APDU is a case 3 short command APDU. * * @param keyRef * - key reference * @return APDU as byte array */ @Deprecated public static byte[] mseSelectPubKeyCertVerification(byte[] keyRef) { byte[] p12 = new byte[] { (byte) 0x81, (byte) 0xB6 }; byte[] data = ByteUtils.concatenate(new byte[] { (byte) 0x83, (byte) keyRef.length }, keyRef); return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } /** * Creates an APDU that is equivalent to the command * "MANAGE SECURITY ENVIRONMENT". The command selects a public key for a * following "EXTERNAL AUTHENTICATE". The created APDU is a case 3 short * command APDU. * * @param keyRef * - key reference * @param algId * - algorithm identifier * @return APDU as byte array */ @Deprecated public static byte[] mseSelectPubKeyExtAuth(byte[] keyRef, byte algId) { byte[] p12 = new byte[] { (byte) 0x81, (byte) 0xA4 }; byte[] data = ByteUtils.concatenate(ByteUtils.concatenate(new byte[] { (byte) 0x83, (byte) keyRef.length }, keyRef), new byte[] { (byte) 0x80, (byte) 0x01, algId }); return genericCommand(COMMAND_MANAGE_SECURITY_ENVIRONMENT, p12, data); } } public static class GeneralAuthenticate { private static final byte COMMAND_GENERAL_AUTHENTICATE = (byte) 0x86; private static final byte GENERAL_AUTHENTICATION_DATA_TAG = (byte) 0x7C; private static final byte[] p12 = new byte[] { (byte) 0x00, (byte) 0x00 }; /** * Creates a new General Authenticate APDU. TR-03110 2.05 Section B.11.2 * APDU: 0x10 0x86 0x00 0x00 0x02 0x7C 0x00 0x00 * * @return General Authenticate APDU */ public static byte[] getNonce() { byte[] command = genericCommand(COMMAND_GENERAL_AUTHENTICATE, p12, new byte[] { GENERAL_AUTHENTICATION_DATA_TAG, (byte) 0x00 }, (short) 0x00); return addCommandChaining(command); } public static byte[] generic(byte tag, byte[] content, boolean commandChaining) { byte[] mappingData = ByteUtils.concatenate(new byte[] { tag, (byte) content.length }, content); byte[] data = ByteUtils.concatenate(new byte[] { GENERAL_AUTHENTICATION_DATA_TAG, (byte) mappingData.length }, mappingData); byte[] command = genericCommand(COMMAND_GENERAL_AUTHENTICATE, p12, data, (short) 0x00); if (commandChaining) { return addCommandChaining(command); } else { return command; } } } public static class PerformSecurityOperation { private static final byte COMMAND_PERFORM_SECURITY_OPERATION = (byte) 0x2A; private static final byte VERIFY_SELF_DESCRIPTIVE_CERTIFICATE = (byte) 0xBE; private static final byte VERIFY_NOT_SELF_DESCRIPTIVE_CERTIFICATE = (byte) 0xAE; /** * Creates an APDU that is equivalent to the command * "PERFORM SECURITY OPERATION". Depending on the size of the parameter * data, the created APDU is either a case 3 short command APDU or a * case 3 extended command APDU. The command verifies a card verifiable * certificate (CVC). * * @param certificate * - CVC to be verified * @return APDU as byte array */ public static byte[] verifySelfDescriptiveCertificate(byte[] certificate) { byte[] verifySelfCert = new byte[] { 0x00, VERIFY_SELF_DESCRIPTIVE_CERTIFICATE }; return genericCommand(COMMAND_PERFORM_SECURITY_OPERATION, verifySelfCert, certificate); } public static byte[] verifyNotSelfDescriptiveCertificate(byte[] certificate) { byte[] verifyNotSelfCert = new byte[] { 0x00, VERIFY_NOT_SELF_DESCRIPTIVE_CERTIFICATE }; return genericCommand(COMMAND_PERFORM_SECURITY_OPERATION, verifyNotSelfCert, certificate); } public static byte[] computeDigitalSignature(byte[] input) { byte[] p12 = new byte[]{(byte)0x9E,(byte) 0x9A}; return genericCommand(COMMAND_PERFORM_SECURITY_OPERATION, p12, input, (short) 0x00); } public static byte[] decipher(byte[] input, short length) { byte[] p12 = new byte[]{(byte)0x80,(byte) 0x86}; return genericCommand(COMMAND_PERFORM_SECURITY_OPERATION, p12, input, length); } // TODO add further pso commands } public static class Read { private static final byte COMMAND_READ_BINARY1 = (byte) 0xB0; private static final byte COMMAND_READ_BINARY2 = (byte) 0xB1; private static final byte COMMAND_READ_RECORD1 = (byte) 0xB2; private static final byte COMMAND_READ_RECORD2 = (byte) 0xB3; public static List<byte[]> positiveResponses() { return new ArrayList<byte[]>() { { add(new byte[] { (byte) 0x90, (byte) 0x00 }); add(new byte[] { (byte) 0x62, (byte) 0x82 }); } }; } public static Transmit makeTransmit(byte[] slotHandle, byte[] cmd) { return CardCommands.makeTransmit(slotHandle, cmd, positiveResponses()); } private static byte[] genericBinary(byte cmd, byte[] p12, byte[] content, short length) { // fix p12 if one byte missing if (p12.length == 1) { p12 = ByteUtils.concatenate((byte) 0x00, p12); } byte[] apdu; if (content == null) { apdu = genericCommand(cmd, p12, length); } else { apdu = genericCommand(cmd, p12, content, length); } return apdu; } public static byte[] binaryWithShortId(byte shortId, short offset, short len) { if (offset > 0xFF) { byte[] dataBytes = ShortUtils.toByteArray(offset); // write length tag dataBytes = ByteUtils.concatenate((byte) dataBytes.length, dataBytes); dataBytes = ByteUtils.concatenate((byte) 0x54, dataBytes); // write discretionary data tag dataBytes = ByteUtils.concatenate((byte) dataBytes.length, dataBytes); dataBytes = ByteUtils.concatenate((byte) 0x53, dataBytes); return genericBinary(COMMAND_READ_BINARY2, new byte[] { 0, shortId }, dataBytes, len); } else { byte p1 = (byte) ((0x1F & shortId) | 0x80); // first bit set and // 5 to 1 is id return genericBinary(COMMAND_READ_BINARY1, new byte[] { p1, (byte) offset }, null, len); } } public static byte[] binaryWithShortId(byte shortId, short offset) { return binaryWithShortId(shortId, offset, (short) 0xFF); } public static byte[] binary(short offset, short len) { byte[] p12 = ShortUtils.toByteArray(offset); if (p12.length == 2) { p12[0] &= 0x7F; // make sure bit 8 is 0 } return genericBinary(COMMAND_READ_BINARY1, p12, null, len); } public static byte[] binary(short offset) { return binary(offset, (short) 0xFF); } public static byte[] binary() { return binary((short) 0x00); } public static byte[] binaryWithExtraOffset(short fileId, short offset, short len) { byte[] p12 = ShortUtils.toByteArray(fileId); // build offset tag structure byte[] content = ShortUtils.toByteArray(offset); content = ByteUtils.concatenate((byte) content.length, content); content = ByteUtils.concatenate((byte) 0x54, content); // returns // tag 0x53 // or 0x73 return genericBinary(COMMAND_READ_BINARY2, p12, content, len); } public static byte[] binaryWithExtraOffset(short fileId, short offset) { return binaryWithExtraOffset(fileId, offset, (short) 0xFF); } private static byte[] genericRecord(byte shortId, byte readType, byte record, short length) { byte p1 = record; byte p2 = (byte) (shortId << 3); p2 |= readType & 0x07; byte[] apdu = genericCommand(COMMAND_READ_RECORD1, new byte[] { p1, p2 }, length); return apdu; } private static byte[] genericRecord(byte shortId, byte readType, byte record, short offset, short length) { byte p1 = record; byte p2 = (byte) (shortId << 3); p2 |= readType & 0x07; byte[] content = ShortUtils.toByteArray(offset); content = ByteUtils.concatenate((byte) content.length, content); content = ByteUtils.concatenate((byte) 0x54, content); byte[] apdu = genericCommand(COMMAND_READ_RECORD1, new byte[] { p1, p2 }, length); return apdu; } public static byte[] recordNumber(byte number) { return genericRecord((byte) 0x00, (byte) 0x04, number, (short) 0xFF); } public static byte[] recordNumber_Ext(byte number) { return genericRecord((byte) 0x00, (byte) 0x04, number, (short) 0xFFFF); } public static byte[] recordNumberWithShortId(byte shortId, byte number) { return genericRecord(shortId, (byte) 0x04, number, (short) 0xFF); } public static byte[] recordNumberWithShortId_Ext(byte shortId, byte number) { return genericRecord(shortId, (byte) 0x04, number, (short) 0xFFFF); } public static byte[] recordsFromNumber(byte number) { return genericRecord((byte) 0x00, (byte) 0x05, number, (short) 0xFF); } public static byte[] recordsNumber_Ext(byte number) { return genericRecord((byte) 0x00, (byte) 0x05, number, (short) 0xFFFF); } // TODO: add other combinations } public static class Select { private static final byte COMMAND_SELECT = (byte) 0xA4; public static List<byte[]> positiveResponses() { return new ArrayList<byte[]>() { { add(new byte[] { (byte) 0x90, (byte) 0x00 }); } }; } public static Transmit makeTransmit(byte[] slotHandle, byte[] cmd) { return CardCommands.makeTransmit(slotHandle, cmd, positiveResponses()); } private static byte[] generic(byte[] fid, byte p1, byte p2, short length) { byte[] p12 = new byte[] { p1, p2 }; byte[] apdu; if ((p2 & 0x0C) != 0x0C) { // check file control information for // response data if (fid == null) { apdu = genericCommand(COMMAND_SELECT, p12, length); } else { apdu = genericCommand(COMMAND_SELECT, p12, fid, length); } } else { if (fid == null) { apdu = genericCommand(COMMAND_SELECT, p12); } else { apdu = genericCommand(COMMAND_SELECT, p12, fid); } } return apdu; } private static byte[] generic(byte[] fid, byte p1, byte p2) { return generic(fid, p1, p2, (short) 0xFF); } private static byte[] generic(byte p1, byte p2) { return generic(null, p1, p2); } /** * Creates an APDU that is equivalent to the command * "SELECT APPLICATION". The created APDU is a case 3 short command * APDU. * * @param aid * - application identifier * @return APDU as byte array */ public static byte[] application(byte[] aid) { return application(aid, (byte) 0x0C); } public static byte[] application_FCI(byte[] aid) { return application(aid, (byte) 0x00); } public static byte[] application_FCP(byte[] aid) { return application(aid, (byte) 0x04); } public static byte[] application_FMD(byte[] aid) { return application(aid, (byte) 0x08); } public static byte[] application_FCI_Ext(byte[] aid) { return application(aid, (byte) 0x00, (short) 0xFFFF); } public static byte[] application_FCP_Ext(byte[] aid) { return application(aid, (byte) 0x04, (short) 0xFFFF); } public static byte[] application_FMD_Ext(byte[] aid) { return application(aid, (byte) 0x08, (short) 0xFFFF); } private static byte[] application(byte[] aid, byte p2) { return generic(aid, (byte) 0x04, p2); } private static byte[] application(byte[] aid, byte p2, short length) { return generic(aid, (byte) 0x04, p2, length); } /** * Creates an APDU that is equivalent to the command "SELECT DIRECTORY". * The created APDU is a case 3 short command APDU. * * @param fid * - file identifier for directory * @return APDU as byte array */ public static byte[] DF(byte[] fid) { return DF(fid, (byte) 0x0C); } public static byte[] DF_FCI(byte[] fid) { return DF(fid, (byte) 0x00); } public static byte[] DF_FCP(byte[] fid) { return DF(fid, (byte) 0x04); } public static byte[] DF_FMD(byte[] fid) { return DF(fid, (byte) 0x08); } public static byte[] DF_FCI_Ext(byte[] fid) { return DF(fid, (byte) 0x00, (short) 0xFFFF); } public static byte[] DF_FCP_Ext(byte[] fid) { return DF(fid, (byte) 0x04, (short) 0xFFFF); } public static byte[] DF_FMD_Ext(byte[] fid) { return DF(fid, (byte) 0x08, (short) 0xFFFF); } private static byte[] DF(byte[] fid, byte p2) { return generic(fid, (byte) 0x01, p2); } private static byte[] DF(byte[] fid, byte p2, short length) { return generic(fid, (byte) 0x01, p2, length); } public static byte[] parent() { return parent((byte) 0x0C); } public static byte[] parent_FCI() { return parent((byte) 0x00); } public static byte[] parent_FCP() { return parent((byte) 0x04); } public static byte[] parent_FMD() { return parent((byte) 0x08); } public static byte[] parent_FCI_Ext() { return parent((byte) 0x00, (short) 0xFFFF); } public static byte[] parent_FCP_Ext() { return parent((byte) 0x04, (short) 0xFFFF); } public static byte[] parent_FMD_Ext() { return parent((byte) 0x08, (short) 0xFFFF); } private static byte[] parent(byte p2) { return generic((byte) 0x03, p2); } private static byte[] parent(byte p2, short length) { return generic(null, (byte) 0x03, p2, length); } /** * Creates an APDU that is equivalent to the command "SELECT FILE". The * created APDU is a case 3 short command APDU. * * @param fid * - file identifier * @return APDU as byte array */ public static byte[] EF(byte[] fid) { return EF(fid, (byte) 0x0C); } public static byte[] EF_FCI(byte[] fid) { return EF(fid, (byte) 0x00); } public static byte[] EF_FCP(byte[] fid) { return EF(fid, (byte) 0x04); } public static byte[] EF_FMD(byte[] fid) { return EF(fid, (byte) 0x08); } public static byte[] EF_FCI_Ext(byte[] fid) { return EF(fid, (byte) 0x00, (short) 0xFFFF); } public static byte[] EF_FCP_Ext(byte[] fid) { return EF(fid, (byte) 0x04, (short) 0xFFFF); } public static byte[] EF_FMD_Ext(byte[] fid) { return EF(fid, (byte) 0x08, (short) 0xFFFF); } private static byte[] EF(byte[] fid, byte p2) { return generic(fid, (byte) 0x02, p2); } private static byte[] EF(byte[] fid, byte p2, short length) { return generic(fid, (byte) 0x02, p2, length); } public static byte[] absolutePath(byte[] path) { return absolutePath(path, (byte) 0x0C); } public static byte[] absolutePath_FCI(byte[] path) { return absolutePath(path, (byte) 0x00); } public static byte[] absolutePath_FCP(byte[] path) { return absolutePath(path, (byte) 0x04); } public static byte[] absolutePath_FMD(byte[] path) { return absolutePath(path, (byte) 0x08); } public static byte[] absolutePath_Ext(byte[] path) { return absolutePath(path, (byte) 0x0C, (short) 0xFFFF); } public static byte[] absolutePath_FCI_Ext(byte[] path) { return absolutePath(path, (byte) 0x00, (short) 0xFFFF); } public static byte[] absolutePath_FCP_Ext(byte[] path) { return absolutePath(path, (byte) 0x04, (short) 0xFFFF); } public static byte[] absolutePath_FMD_Ext(byte[] path) { return absolutePath(path, (byte) 0x08, (short) 0xFFFF); } private static byte[] absolutePath(byte[] path, byte p2) { return generic(path, (byte) 0x08, p2); } private static byte[] absolutePath(byte[] path, byte p2, short length) { return generic(path, (byte) 0x08, p2, length); } public static byte[] relativePath(byte[] path) { return relativePath(path, (byte) 0x0C); } public static byte[] relativePath_FCI(byte[] path) { return relativePath(path, (byte) 0x00); } public static byte[] relativePath_FCP(byte[] path) { return relativePath(path, (byte) 0x04); } public static byte[] relativePath_FMD(byte[] path) { return relativePath(path, (byte) 0x08); } public static byte[] relativePath_Ext(byte[] path) { return relativePath(path, (byte) 0x0C, (short) 0xFFFF); } public static byte[] relativePath_FCI_Ext(byte[] path) { return relativePath(path, (byte) 0x00, (short) 0xFFFF); } public static byte[] relativePath_FCP_Ext(byte[] path) { return relativePath(path, (byte) 0x04, (short) 0xFFFF); } public static byte[] relativePath_FMD_Ext(byte[] path) { return relativePath(path, (byte) 0x08, (short) 0xFFFF); } private static byte[] relativePath(byte[] path, byte p2) { return generic(path, (byte) 0x09, p2); } private static byte[] relativePath(byte[] path, byte p2, short length) { return generic(path, (byte) 0x09, p2, length); } private static final byte[] MF_fid = new byte[] { (byte) 0x3F, (byte) 0x00 }; /** * Creates an APDU that selects the MASTER FILE. The created APDU is a * case 1 command APDU. * * @return APDU as byte array */ public static byte[] MF() { return MF((byte) 0x0C); } public static byte[] MF_FCI() { return MF((byte) 0x00); } public static byte[] MF_FCP() { return MF((byte) 0x04); } public static byte[] MF_FMD() { return MF((byte) 0x08); } public static byte[] MF_FCI_Ext() { return MF((byte) 0x00, (short) 0xFFFF); } public static byte[] MF_FCP_Ext() { return MF((byte) 0x04, (short) 0xFFFF); } public static byte[] MF_FMD_Ext() { return MF((byte) 0x08, (short) 0xFFFF); } private static byte[] MF(byte p2) { return generic(MF_fid, (byte) 0x00, p2); } private static byte[] MF(byte p2, short length) { return generic(MF_fid, (byte) 0x00, p2, length); } } }