/**************************************************************************** * 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.tlv.iso7816; import java.util.LinkedList; import java.util.List; import org.openecard.common.tlv.Parser; import org.openecard.common.tlv.TLV; import org.openecard.common.tlv.TLVException; import org.openecard.common.util.ByteUtils; /** * * @author Tobias Wich <tobias.wich@ecsec.de> */ public class FCP { private final TLV tlv; private Long numBytes; private Long numBytesStructure; private DataElements dataElements; private List<byte[]> fileIdentifiers = new LinkedList<byte[]>(); private List<byte[]> dfNames = new LinkedList<byte[]>(); private List<byte[]> proprietaryInformationNoTLV = new LinkedList<byte[]>(); private List<byte[]> proprietarySecurityAttribute = new LinkedList<byte[]>(); private byte[] fciExtensionEf; private byte[] shortEfIdentifier; private Byte lifeCycleStatusByte; private byte[] securityAttributeReferenceExpanded; private byte[] securityAttributeCompact; private List<byte[]> securityEnvironmentTemplateEfs = new LinkedList<byte[]>(); private Byte channelSecurityAttribute; private byte[] securityAttributeTemplateForDataObject; private byte[] securityAttributeTemplateProprietary; private List<TLV> dataObjectTemplates = new LinkedList<TLV>(); private TLV proprietaryInformationTLV; private byte[] securityAttributeTemplateExpanded; private byte[] cryptographicMechanismIdentifierTemplate; public FCP(TLV tlv) throws TLVException { this.tlv = tlv; if (tlv.getTagNumWithClass() != 0x62) { throw new TLVException("Data doesn't represent an FCP."); } // declare helper variables List<byte[]> descriptorBytes = new LinkedList<byte[]>(); Parser p = new Parser(tlv.getChild()); TLV next; while ((next = p.next(0)) != null) { // num bytes if (next.getTagNumWithClass() == 0x80) { numBytes = new Long(ByteUtils.toLong(next.getValue())); } if (next.getTagNumWithClass() == 0x81) { // length == 2 numBytesStructure = new Long(ByteUtils.toLong(next.getValue())); } // descriptor bytes if (next.getTagNumWithClass() == 0x82) { descriptorBytes.add(next.getValue()); } // file identifier if (next.getTagNumWithClass() == 0x83) { fileIdentifiers.add(next.getValue()); } // df names if (next.getTagNumWithClass() == 0x84) { dfNames.add(next.getValue()); } // proprietary information if (next.getTagNumWithClass() == 0x85) { proprietaryInformationNoTLV.add(next.getValue()); } // proprietary security attribute if (next.getTagNumWithClass() == 0x86) { proprietarySecurityAttribute.add(next.getValue()); } // file identifier of fci extension if (next.getTagNumWithClass() == 0x87) { fciExtensionEf = next.getValue(); } // short ef identifier if (next.getTagNumWithClass() == 0x88) { shortEfIdentifier = next.getValue(); } // lifecycle status byte if (next.getTagNumWithClass() == 0x8A) { lifeCycleStatusByte = new Byte(next.getValue()[0]); } // security attribute reference expanded form // TODO: make subtype if (next.getTagNumWithClass() == 0x8B) { securityAttributeReferenceExpanded = next.getValue(); } // security attribute compact form // TODO: make subtype if (next.getTagNumWithClass() == 0x8C) { securityAttributeCompact = next.getValue(); } // security environment template EFs if (next.getTagNumWithClass() == 0x8D) { securityEnvironmentTemplateEfs.add(next.getValue()); } // channel security attribute if (next.getTagNumWithClass() == 0x8E) { channelSecurityAttribute = new Byte(next.getValue()[0]); } // securityAttributeTemplateForDataObject if (next.getTagNumWithClass() == 0xA0) { securityAttributeTemplateForDataObject = next.getValue(); } // securityAttributeTemplateProprietary if (next.getTagNumWithClass() == 0xA1) { securityAttributeTemplateProprietary = next.getValue(); } // dataObjectTemplates if (next.getTagNumWithClass() == 0xA2) { dataObjectTemplates.add(next); } // proprietaryInformationTLV if (next.getTagNumWithClass() == 0xA5) { proprietaryInformationTLV = next; } // securityAttributeTemplateExpanded if (next.getTagNumWithClass() == 0xAB) { securityAttributeTemplateExpanded = next.getValue(); } // cryptographicMechanismIdentifierTemplate if (next.getTagNumWithClass() == 0xAC) { cryptographicMechanismIdentifierTemplate = next.getValue(); } } // construct higher level objects dataElements = new DataElements(descriptorBytes); } public FCP(byte[] data) throws TLVException { this(TLV.fromBER(data)); } public byte[] toBER() { try { return tlv.toBER(); } catch (TLVException ex) { return null; // can not happen as it is created fom byte[] before } } public Long getNumBytes() { return this.numBytes; } public DataElements getDataElements() { return dataElements; } /** len=2 */ public List<byte[]> fileIdentifiers() { return fileIdentifiers; } /** len=..* */ public List<byte[]> DF_Names() { return dfNames; } // TODO: implement further tags in FCP public String toString(String prefix) { StringBuilder b = new StringBuilder(4096); String indent = prefix + " "; String subindent = indent + " "; b.append(prefix); b.append("FCP:\n"); b.append(indent); b.append("num-bytes="); b.append(numBytes); b.append(" num-bytes-structure="); b.append(numBytesStructure); b.append("\n"); b.append(dataElements.toString(indent)); b.append("\n"); b.append(indent); b.append("File-Identifiers:\n"); for (byte[] next : fileIdentifiers) { b.append(subindent); b.append(ByteUtils.toHexString(next)); b.append("\n"); } b.append("DF-Names:\n"); for (byte[] next : dfNames) { b.append(subindent); b.append(ByteUtils.toHexString(next)); b.append("\n"); } // proprietaryInformationNoTLV // proprietarySecurityAttribute // fciExtensionEf // shortEfIdentifier if (shortEfIdentifier != null) { b.append(indent); b.append("short-EF-identifier: "); b.append(ByteUtils.toHexString(shortEfIdentifier)); b.append("\n"); } // lifeCycleStatusByte // securityAttributeReferenceExpanded // securityAttributeCompact // securityEnvironmentTemplateEfs // channelSecurityAttribute // securityAttributeTemplateForDataObject // securityAttributeTemplateProprietary // dataObjectTemplates b.append(indent); b.append("DataObjectTemplates:\n"); for (TLV next : dataObjectTemplates) { b.append(subindent); b.append("DataObjectTemplate:"); b.append(next.toString(subindent + " ")); b.append("\n"); } // proprietaryInformationTLV // securityAttributeTemplateExpanded // cryptographicMechanismIdentifierTemplate return b.toString(); } @Override public String toString() { return toString(""); } }