/**************************************************************************** * 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.ifd; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.List; import org.openecard.common.ECardConstants; /** * * @author Tobias Wich <tobias.wich@ecsec.de> */ public class PACECapabilities { /** * PACE Capabilities as defined in PCSC-10 AMD1.1 p. 6 */ public enum PACECapability { DestroyPACEChannel(0x80), GenericPACE(0x40), // GermanEID(0x20), QES(0x10); public final long number; private PACECapability(long number) { this.number = number; } public static PACECapability getCapability(long number) { for (PACECapability next : values()) { if (next.number == number) { return next; } } return null; } public String getProtocol() { return ECardConstants.Protocol.PACE + "." + number; } } private final BitSet capabilities; public PACECapabilities(byte[] capabilitiesStructure) { if (capabilitiesStructure.length == 1) { // special case for reiner sct readers capabilities = makeBitSet(capabilitiesStructure); } else { // standard way byte length = capabilitiesStructure[0]; byte[] data = Arrays.copyOfRange(capabilitiesStructure, 1, length+1); capabilities = makeBitSet(data); } } public List<Long> getFeatures() { List<Long> result = new ArrayList<Long>(capabilities.cardinality()); for (int i = capabilities.nextSetBit(0); i >= 0; i = capabilities.nextSetBit(i+1)) { // operate on index i here result.add(Long.valueOf(1<<i)); } return result; } public List<PACECapability> getFeaturesEnum() { List<Long> features = getFeatures(); List<PACECapability> result = new ArrayList<PACECapability>(features.size()); for (Long next : features) { PACECapability cap = PACECapability.getCapability(next); if (next != null) { result.add(cap); } } return result; } private BitSet makeBitSet(byte[] d) { BitSet b = new BitSet(d.length*8); for (int i=0; i<d.length; i++) { byte next = d[i]; for (int j=0; j<8; j++) { boolean isSet = ((next >> j) & 0x01) == 1; if (isSet) { b.set((i*8)+j); } } } return b; } }