/**************************************************************************** * 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.sal.state; import iso.std.iso_iec._24727.tech.schema.CardApplicationPathType; import iso.std.iso_iec._24727.tech.schema.CardInfoType; import iso.std.iso_iec._24727.tech.schema.ConnectionHandleType; import iso.std.iso_iec._24727.tech.schema.DIDAuthenticationStateType; import iso.std.iso_iec._24727.tech.schema.DIDInfoType; import iso.std.iso_iec._24727.tech.schema.DIDStructureType; import iso.std.iso_iec._24727.tech.schema.SecurityConditionType; import java.math.BigInteger; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.openecard.addon.sal.SALProtocol; import org.openecard.common.WSHelper; import org.openecard.common.sal.state.cif.CardApplicationWrapper; import org.openecard.common.sal.state.cif.CardInfoWrapper; import org.openecard.common.sal.state.cif.DIDInfoWrapper; import org.openecard.common.sal.state.cif.DataSetInfoWrapper; import org.openecard.common.tlv.iso7816.FCP; import org.openecard.common.util.ByteArrayWrapper; /** * * @author Tobias Wich <tobias.wich@ecsec.de> * @author Dirk Petrautzki <petrautzki@hs-coburg.de> */ public class CardStateEntry implements Comparable<CardStateEntry> { // this number is used as an number authority, so each entry can have a distinct number private static int numberRegistry = 0; private synchronized static int nextNumber() { return numberRegistry++; } private final int serialNumber; private Set<DIDInfoType> authenticatedDIDs = new HashSet<DIDInfoType>(); private final ConnectionHandleType handle; private final CardInfoWrapper infoObject; private Map<String, SALProtocol> protoObjects = new TreeMap<String, SALProtocol>(); private FCP lastSelectedEfFCP; public CardStateEntry(ConnectionHandleType handle, CardInfoType cif) { serialNumber = nextNumber(); infoObject = new CardInfoWrapper(cif); this.handle = handle; this.handle.setCardApplication(getImplicitlySelectedApplicationIdentifier()); } public String getCardType() { return infoObject.getCardType(); } public void setCurrentCardApplication(byte[] currentCardApplication) { this.handle.setCardApplication(currentCardApplication); } public CardApplicationWrapper getCurrentCardApplication() { return infoObject.getCardApplication(this.handle.getCardApplication()); } public Set<DIDInfoType> getAuthenticatedDIDs() { return authenticatedDIDs; } public void addAuthenticated(String didName, byte[] cardApplication){ this.authenticatedDIDs.add(this.infoObject.getDIDInfo(didName, cardApplication)); } public void removeAuthenticated(DIDInfoType didInfo){ this.authenticatedDIDs.remove(didInfo); } public ConnectionHandleType handleCopy() { return WSHelper.copyHandle(handle); } public CardApplicationPathType pathCopy() { return WSHelper.copyPath(handle); } public boolean hasSlotIdx() { return handle.getSlotIndex() != null; } public boolean matchSlotIdx(BigInteger idx) { BigInteger otherIdx = handle.getSlotIndex(); if (idx != null && otherIdx != null && otherIdx.equals(idx)) { return true; } return false; } public String getIfdName() { return handle.getIFDName(); } public CardInfoWrapper getInfo() { return infoObject; } public void setSlotHandle(byte[] slotHandle){ this.handle.setSlotHandle(slotHandle); } public SALProtocol setProtocol(String type, SALProtocol proto) { protoObjects.put(type, proto); return proto; } public SALProtocol getProtocol(String type) { return protoObjects.get(type); } public void removeProtocol(String type) { protoObjects.remove(type); } public void removeAllProtocols() { protoObjects.clear(); } public void setFCPOfSelectedEF(FCP fcp) { lastSelectedEfFCP = fcp; } public void unsetFCPOfSelectedEF() { lastSelectedEfFCP = null; } public FCP getFCPOfSelectedEF() { return lastSelectedEfFCP; } /** * * @param didName Name of the DID * @param cardApplication Identifier of the cardapplication * @return DIDStructure for the specified didName and cardapplication or null, * if no such did exists. */ public DIDStructureType getDIDStructure(String didName, byte[] cardApplication) { DIDStructureType didStructure = this.infoObject.getDIDStructure(didName, cardApplication); if (didStructure != null) { didStructure.setAuthenticated(this.isAuthenticated(didName, cardApplication)); } return didStructure; } public boolean isAuthenticated(String didName, byte[] cardApplication) { if (this.getAuthenticatedDIDs().contains(this.infoObject.getDIDInfo(didName, cardApplication))) { return true; } else { return false; } } private boolean checkSecurityCondition(SecurityConditionType securityCondition) { byte[] cardApplication = infoObject.getImplicitlySelectedApplication(); try{ if(securityCondition.isAlways()) { return true; } } catch (NullPointerException e){ // ignore } if (securityCondition.getDIDAuthentication()!=null) { DIDAuthenticationStateType didAuthenticationState = securityCondition.getDIDAuthentication(); if (didAuthenticationState.isDIDState()) { return isAuthenticated(didAuthenticationState.getDIDName(), cardApplication); } else { return !isAuthenticated(didAuthenticationState.getDIDName(), cardApplication); } } else if (securityCondition.getOr() != null) { for (SecurityConditionType securityConditionOR : securityCondition.getOr().getSecurityCondition()) { if (checkSecurityCondition(securityConditionOR)) { return true; } } } else if (securityCondition.getAnd() != null) { for(SecurityConditionType securityConditionAND : securityCondition.getAnd().getSecurityCondition()) { if (!checkSecurityCondition(securityConditionAND)) { return false; } } return true; } else if (securityCondition.getNot() != null) { return !checkSecurityCondition(securityCondition.getNot()); } return false; } public boolean checkDIDSecurityCondition(byte[] cardApplication, String didName, Enum<?> serviceAction) { CardApplicationWrapper application = this.infoObject.getCardApplications().get(new ByteArrayWrapper(cardApplication)); DIDInfoWrapper dataSetInfo = application.getDIDInfo(didName); SecurityConditionType securityCondition = dataSetInfo.getSecurityCondition(serviceAction); if (securityCondition != null) { return checkSecurityCondition(securityCondition); } else { return false; } } public boolean checkApplicationSecurityCondition(byte[] applicationIdentifier, Enum<?> serviceAction) { if (applicationIdentifier == null) { applicationIdentifier = infoObject.getImplicitlySelectedApplication(); } CardApplicationWrapper application = this.infoObject.getCardApplications().get(new ByteArrayWrapper(applicationIdentifier)); SecurityConditionType securityCondition = application.getSecurityCondition(serviceAction); if (securityCondition != null) { return checkSecurityCondition(securityCondition); } else { return false; } } public boolean checkDataSetSecurityCondition(byte[] cardApplication, String dataSetName, Enum<?> serviceAction) { CardApplicationWrapper application = this.infoObject.getCardApplications().get(new ByteArrayWrapper(cardApplication)); DataSetInfoWrapper dataSetInfo = application.getDataSetInfo(dataSetName); SecurityConditionType securityCondition = dataSetInfo.getSecurityCondition(serviceAction); if (securityCondition != null) { return checkSecurityCondition(securityCondition); } else { return false; } } public final byte[] getImplicitlySelectedApplicationIdentifier() { return this.infoObject.getImplicitlySelectedApplication(); } /// /// needed to sort these entries in sets /// @Override public int compareTo(CardStateEntry o) { return this.serialNumber - o.serialNumber; } @Override public boolean equals(Object obj) { if (obj instanceof CardStateEntry) { CardStateEntry other = (CardStateEntry) obj; return this == obj || this.serialNumber == other.serialNumber; } return super.equals(obj); } @Override public int hashCode() { int hash = 3; hash = 53 * hash + this.serialNumber; return hash; } }