package de.persosim.simulator.protocols.auxVerification;
import java.io.FileNotFoundException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import org.globaltester.logging.InfoSource;
import de.persosim.simulator.apdu.ResponseApdu;
import de.persosim.simulator.cardobjects.AuxDataObject;
import de.persosim.simulator.cardobjects.CardObject;
import de.persosim.simulator.cardobjects.CardObjectUtils;
import de.persosim.simulator.cardobjects.MasterFile;
import de.persosim.simulator.cardobjects.OidIdentifier;
import de.persosim.simulator.exception.AccessDeniedException;
import de.persosim.simulator.exception.VerificationException;
import de.persosim.simulator.platform.CardStateAccessor;
import de.persosim.simulator.platform.Iso7816;
import de.persosim.simulator.platform.PlatformUtil;
import de.persosim.simulator.processing.ProcessingData;
import de.persosim.simulator.protocols.GenericOid;
import de.persosim.simulator.protocols.Oid;
import de.persosim.simulator.protocols.Protocol;
import de.persosim.simulator.protocols.SecInfoPublicity;
import de.persosim.simulator.protocols.ca.ChipAuthenticationMechanism;
import de.persosim.simulator.protocols.ta.AuthenticatedAuxiliaryData;
import de.persosim.simulator.protocols.ta.TerminalAuthenticationMechanism;
import de.persosim.simulator.secstatus.SecMechanism;
import de.persosim.simulator.secstatus.SecStatus.SecContext;
import de.persosim.simulator.tlv.TlvConstants;
import de.persosim.simulator.tlv.TlvDataObject;
import de.persosim.simulator.tlv.TlvDataObjectContainer;
public class AuxProtocol implements Protocol, Iso7816, InfoSource, TlvConstants {
CardStateAccessor cardState;
@Override
public String getProtocolName() {
return "AUX";
}
@Override
public void setCardStateAccessor(CardStateAccessor cardState) {
this.cardState = cardState;
}
@Override
public Collection<TlvDataObject> getSecInfos(SecInfoPublicity publicity, MasterFile mf) {
return Collections.emptySet();
}
@Override
public void process(ProcessingData processingData) {
if ((processingData.getCommandApdu().getCla() == (byte) 0x80) && (processingData.getCommandApdu().getIns() == INS_20_VERIFY)){
//check for ca
HashSet<Class<? extends SecMechanism>> previousMechanisms = new HashSet<>();
previousMechanisms.add(ChipAuthenticationMechanism.class);
Collection<SecMechanism> currentMechanisms = cardState.getCurrentMechanisms(SecContext.APPLICATION, previousMechanisms);
if (currentMechanisms.size() == 0){
ResponseApdu resp = new ResponseApdu(PlatformUtil.SW_4982_SECURITY_STATUS_NOT_SATISFIED);
processingData.updateResponseAPDU(this, "The AUX protocol can not be executed without a previous CA", resp);
/* there is nothing more to be done here */
return;
}
TlvDataObjectContainer commandData = processingData.getCommandApdu().getCommandDataObjectContainer();
if (commandData.containsTlvDataObject(TlvConstants.TAG_06)){
try{
Oid oid = new GenericOid(commandData.getTlvDataObject(TlvConstants.TAG_06).getValueField());
processOid(processingData, oid);
ResponseApdu resp = new ResponseApdu(Iso7816.SW_9000_NO_ERROR);
processingData.updateResponseAPDU(this, "Auxiliary data verification successfull", resp);
/* there is nothing more to be done here */
return;
} catch (IllegalArgumentException e){
ResponseApdu resp = new ResponseApdu(PlatformUtil.SW_4A80_WRONG_DATA);
processingData.updateResponseAPDU(this, "The given OID is not valid", resp);
/* there is nothing more to be done here */
return;
} catch (FileNotFoundException e) {
ResponseApdu resp = new ResponseApdu(PlatformUtil.SW_4A88_REFERENCE_DATA_NOT_FOUND);
processingData.updateResponseAPDU(this, "The referenced data could not be found", resp);
/* there is nothing more to be done here */
return;
} catch (VerificationException e) {
ResponseApdu resp = new ResponseApdu(SW_6300_AUTHENTICATION_FAILED);
processingData.updateResponseAPDU(this, "Auxiliary data verification failed", resp);
/* there is nothing more to be done here */
return;
} catch (AccessDeniedException e) {
ResponseApdu resp = new ResponseApdu(SW_6982_SECURITY_STATUS_NOT_SATISFIED);
processingData.updateResponseAPDU(this, "Auxiliary data verification failed - Access to data not allowed", resp);
/* there is nothing more to be done here */
return;
}
} else {
ResponseApdu resp = new ResponseApdu(PlatformUtil.SW_4A80_WRONG_DATA);
processingData.updateResponseAPDU(this, "Missing an OID", resp);
/* there is nothing more to be done here */
return;
}
}
}
private void processOid(ProcessingData processingData, Oid oid) throws VerificationException, FileNotFoundException, AccessDeniedException {
//get necessary information stored in TA
Collection<Class<? extends SecMechanism>> previousMechanisms = new HashSet<>();
previousMechanisms.add(TerminalAuthenticationMechanism.class);
Collection<SecMechanism> currentMechanisms = cardState.getCurrentMechanisms(SecContext.APPLICATION, previousMechanisms);
TerminalAuthenticationMechanism taMechanism = null;
if (currentMechanisms.size() > 0){
taMechanism = (TerminalAuthenticationMechanism) currentMechanisms.toArray()[0];
Collection<AuthenticatedAuxiliaryData> auxDataFromTa = taMechanism.getAuxiliaryData();
CardObject auxDataCandidate = CardObjectUtils.getSpecificChild(cardState.getMasterFile(), new OidIdentifier(oid));
AuxDataObject auxDataObject = null;
if (auxDataCandidate instanceof AuxDataObject){
auxDataObject = (AuxDataObject) auxDataCandidate;
} else {
throw new FileNotFoundException("The card object using the OID " + oid.toString() + " is not a AUX data object");
}
if (auxDataFromTa != null){
AuthenticatedAuxiliaryData expectedAuxData = null;
for (AuthenticatedAuxiliaryData current : auxDataFromTa){
if(oid.equals(current.getObjectIdentifier())) {
expectedAuxData = current;
break;
}
}
if(expectedAuxData == null) {
throw new FileNotFoundException("No auxiliary data was stored during TA matching the provided OID");
} else {
if (auxDataObject.verify(expectedAuxData)){
return;
}
}
} else {
throw new FileNotFoundException("No auxiliary data was stored during TA");
}
throw new VerificationException("no auxiliary data verified successfully");
}
}
@Override
public void reset() {
}
@Override
public String getIDString() {
return "AUX protocol";
}
@Override
public boolean isMoveToStackRequested() {
return false;
}
}