use of org.openecard.ifd.scio.wrapper.TerminalInfo in project open-ecard by ecsec.
the class IFD method getIFDCapabilities.
@Override
public GetIFDCapabilitiesResponse getIFDCapabilities(GetIFDCapabilities parameters) {
GetIFDCapabilitiesResponse response;
// you thought of a different IFD obviously
if (!ByteUtils.compare(ctxHandle, parameters.getContextHandle())) {
String msg = "Invalid context handle specified.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_CONTEXT_HANDLE, msg);
response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
return response;
}
try {
TerminalInfo info;
String ifdName = parameters.getIFDName();
try {
SingleThreadChannel channel = cm.openMasterChannel(ifdName);
info = new TerminalInfo(cm, channel);
} catch (NoSuchTerminal ex) {
// continue without a channel
SCIOTerminal term = cm.getTerminals().getTerminal(ifdName);
info = new TerminalInfo(cm, term);
}
IFDCapabilitiesType cap = new IFDCapabilitiesType();
// slot capability
SlotCapabilityType slotCap = info.getSlotCapability();
cap.getSlotCapability().add(slotCap);
// ask protocol factory which types it supports
List<String> protocols = slotCap.getProtocol();
for (String proto : protocolFactories.protocols()) {
if (!protocols.contains(proto)) {
protocols.add(proto);
}
}
// TODO: PIN Compare should be a part of establishChannel and thus just appear in the software protocol list
if (!protocols.contains(ECardConstants.Protocol.PIN_COMPARE)) {
protocols.add(ECardConstants.Protocol.PIN_COMPARE);
}
// display capability
DisplayCapabilityType dispCap = info.getDisplayCapability();
if (dispCap != null) {
cap.getDisplayCapability().add(dispCap);
}
// keypad capability
KeyPadCapabilityType keyCap = info.getKeypadCapability();
if (keyCap != null) {
cap.getKeyPadCapability().add(keyCap);
}
// biosensor capability
BioSensorCapabilityType bioCap = info.getBiosensorCapability();
if (bioCap != null) {
cap.getBioSensorCapability().add(bioCap);
}
// acoustic and optical elements
cap.setOpticalSignalUnit(info.isOpticalSignal());
cap.setAcousticSignalUnit(info.isAcousticSignal());
// prepare response
response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, WSHelper.makeResultOK());
response.setIFDCapabilities(cap);
return response;
} catch (NullPointerException | NoSuchTerminal ex) {
String msg = String.format("Requested terminal not found.");
LOG.warn(msg, ex);
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.Terminal.UNKNOWN_IFD, msg);
response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
return response;
} catch (SCIOException ex) {
String msg = String.format("Failed to request status from terminal.");
// use debug when card has been removed, as this happens all the time
SCIOErrorCode code = ex.getCode();
if (!(code == SCIOErrorCode.SCARD_E_NO_SMARTCARD || code == SCIOErrorCode.SCARD_W_REMOVED_CARD)) {
LOG.warn(msg, ex);
} else {
LOG.debug(msg, ex);
}
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
return response;
}
}
use of org.openecard.ifd.scio.wrapper.TerminalInfo in project open-ecard by ecsec.
the class IFD method destroyChannel.
@Override
public DestroyChannelResponse destroyChannel(DestroyChannel parameters) {
try {
DestroyChannelResponse destroyChannelResponse = new DestroyChannelResponse();
byte[] slotHandle = parameters.getSlotHandle();
SingleThreadChannel channel = cm.getSlaveChannel(slotHandle);
TerminalInfo termInfo = new TerminalInfo(cm, channel);
// check if it is PACE and try to perform native implementation
// get pace capabilities
List<PACECapabilities.PACECapability> paceCapabilities = termInfo.getPACECapabilities();
if (paceCapabilities.contains(PACECapabilities.PACECapability.DestroyPACEChannel)) {
ExecutePACERequest execPaceReq = new ExecutePACERequest(ExecutePACERequest.Function.DestroyPACEChannel);
byte[] reqData = execPaceReq.toBytes();
LOG.debug("executeCtrlCode request: {}", ByteUtils.toHexString(reqData));
// execute pace
Map<Integer, Integer> features = termInfo.getFeatureCodes();
byte[] resData = channel.transmitControlCommand(features.get(PCSCFeatures.EXECUTE_PACE), reqData);
LOG.debug("Response of executeCtrlCode: {}", ByteUtils.toHexString(resData));
// evaluate response
ExecutePACEResponse execPaceRes = new ExecutePACEResponse(resData);
if (execPaceRes.isError()) {
destroyChannelResponse = WSHelper.makeResponse(DestroyChannelResponse.class, execPaceRes.getResult());
}
}
channel.removeSecureMessaging();
if (destroyChannelResponse.getResult() == null) {
Result r = new Result();
r.setResultMajor(ECardConstants.Major.OK);
destroyChannelResponse.setResult(r);
}
return destroyChannelResponse;
} catch (Throwable t) {
return WSHelper.makeResponse(DestroyChannelResponse.class, WSHelper.makeResult(t));
}
}
use of org.openecard.ifd.scio.wrapper.TerminalInfo in project open-ecard by ecsec.
the class IFD method controlIFD.
/**
* Note: the first byte of the command data is the control code.
*/
@Override
public ControlIFDResponse controlIFD(ControlIFD parameters) {
ControlIFDResponse response;
if (!hasContext()) {
String msg = "Context not initialized.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(ControlIFDResponse.class, r);
return response;
}
byte[] handle = parameters.getSlotHandle();
byte[] command = parameters.getCommand();
if (handle == null || command == null) {
String msg = "Missing parameter.";
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(ControlIFDResponse.class, r);
return response;
}
byte ctrlCode = command[0];
command = Arrays.copyOfRange(command, 1, command.length);
try {
SingleThreadChannel ch = cm.getSlaveChannel(handle);
TerminalInfo info = new TerminalInfo(cm, ch);
Integer featureCode = info.getFeatureCodes().get(Integer.valueOf(ctrlCode));
// see if the terminal can deal with that
if (featureCode != null) {
byte[] resultCommand = ch.transmitControlCommand(featureCode, command);
// evaluate result
Result result = evaluateControlIFDRAPDU(resultCommand);
response = WSHelper.makeResponse(ControlIFDResponse.class, result);
response.setResponse(resultCommand);
return response;
} else {
String msg = "The terminal is not capable of performing the requested action.";
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(ControlIFDResponse.class, r);
return response;
}
} catch (NoSuchChannel | IllegalStateException ex) {
String msg = "The card or the terminal is not available anymore.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.Terminal.UNKNOWN_IFD, msg);
response = WSHelper.makeResponse(ControlIFDResponse.class, r);
LOG.warn(msg, ex);
return response;
} catch (SCIOException ex) {
String msg = "Unknown error while sending transmit control command.";
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(ControlIFDResponse.class, r);
LOG.warn(msg, ex);
return response;
}
}
use of org.openecard.ifd.scio.wrapper.TerminalInfo in project open-ecard by ecsec.
the class IFD method establishChannel.
@Override
public EstablishChannelResponse establishChannel(EstablishChannel parameters) {
byte[] slotHandle = parameters.getSlotHandle();
try {
SingleThreadChannel channel = cm.getSlaveChannel(slotHandle);
TerminalInfo termInfo = new TerminalInfo(cm, channel);
DIDAuthenticationDataType protoParam = parameters.getAuthenticationProtocolData();
String protocol = protoParam.getProtocol();
// check if it is PACE and try to perform native implementation
// get pace capabilities
List<PACECapabilities.PACECapability> paceCapabilities = termInfo.getPACECapabilities();
List<String> supportedProtos = TerminalInfo.buildPACEProtocolList(paceCapabilities);
// i don't care which type is supported, i try it anyways
if (!supportedProtos.isEmpty() && supportedProtos.get(0).startsWith(protocol)) {
// yeah, PACE seems to be supported by the reader, big win
PACEInputType paceParam = new PACEInputType(protoParam);
// extract variables needed for pace
byte pinID = paceParam.getPINID();
// optional elements
byte[] chat = paceParam.getCHAT();
String pin = paceParam.getPIN();
byte[] certDesc = paceParam.getCertificateDescription();
// prepare pace data structures
// TODO: add supplied PIN
EstablishPACERequest estPaceReq = new EstablishPACERequest(pinID, chat, null, certDesc);
ExecutePACERequest execPaceReq = new ExecutePACERequest(ExecutePACERequest.Function.EstablishPACEChannel, estPaceReq.toBytes());
// TODO: check if this additional check is really necessary
if (estPaceReq.isSupportedType(paceCapabilities)) {
byte[] reqData = execPaceReq.toBytes();
LOG.debug("executeCtrlCode request: {}", ByteUtils.toHexString(reqData));
// execute pace
Map<Integer, Integer> features = termInfo.getFeatureCodes();
byte[] resData = channel.transmitControlCommand(features.get(PCSCFeatures.EXECUTE_PACE), reqData);
LOG.debug("Response of executeCtrlCode: {}", ByteUtils.toHexString(resData));
// evaluate response
ExecutePACEResponse execPaceRes = new ExecutePACEResponse(resData);
if (execPaceRes.isError()) {
return WSHelper.makeResponse(EstablishChannelResponse.class, execPaceRes.getResult());
}
EstablishPACEResponse estPaceRes = new EstablishPACEResponse(execPaceRes.getData());
// get values and prepare response
PACEOutputType authDataResponse = paceParam.getOutputType();
// mandatory fields
authDataResponse.setRetryCounter(estPaceRes.getRetryCounter());
authDataResponse.setEFCardAccess(estPaceRes.getEFCardAccess());
// optional fields
if (estPaceRes.hasCurrentCAR()) {
authDataResponse.setCurrentCAR(estPaceRes.getCurrentCAR());
}
if (estPaceRes.hasPreviousCAR()) {
authDataResponse.setPreviousCAR(estPaceRes.getPreviousCAR());
}
if (estPaceRes.hasIDICC()) {
authDataResponse.setIDPICC(estPaceRes.getIDICC());
}
// create response type and return
EstablishChannelResponse response = WSHelper.makeResponse(EstablishChannelResponse.class, WSHelper.makeResultOK());
response.setAuthenticationProtocolData(authDataResponse.getAuthDataType());
return response;
}
}
// check out available software protocols
if (this.protocolFactories.contains(protocol)) {
ProtocolFactory factory = this.protocolFactories.get(protocol);
Protocol protoImpl = factory.createInstance();
EstablishChannelResponse response = protoImpl.establish(parameters, env.getDispatcher(), this.gui);
// register protocol instance for secure messaging when protocol was processed successful
if (response.getResult().getResultMajor().equals(ECardConstants.Major.OK)) {
channel.addSecureMessaging(protoImpl);
}
return response;
}
// if this point is reached a native implementation is not present, try registered protocols
Result r = WSHelper.makeResultUnknownError("No such protocol available in this IFD.");
return WSHelper.makeResponse(EstablishChannelResponse.class, r);
} catch (Throwable t) {
return WSHelper.makeResponse(EstablishChannelResponse.class, WSHelper.makeResult(t));
}
}
use of org.openecard.ifd.scio.wrapper.TerminalInfo in project open-ecard by ecsec.
the class IFD method getStatus.
@Override
public GetStatusResponse getStatus(GetStatus parameters) {
GetStatusResponse response;
// you thought of a different IFD obviously
if (!ByteUtils.compare(ctxHandle, parameters.getContextHandle())) {
String msg = "Invalid context handle specified.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_CONTEXT_HANDLE, msg);
response = WSHelper.makeResponse(GetStatusResponse.class, r);
return response;
}
// get specific ifd or all if no specific one is requested
List<SCIOTerminal> ifds = new LinkedList<>();
try {
String requestedIfd = parameters.getIFDName();
if (requestedIfd != null) {
try {
SCIOTerminal t = cm.getTerminals().getTerminal(requestedIfd);
ifds.add(t);
} catch (NoSuchTerminal ex) {
String msg = "The requested IFD name does not exist.";
LOG.warn(msg, ex);
String minor = ECardConstants.Minor.IFD.Terminal.UNKNOWN_IFD;
Result r = WSHelper.makeResult(ECardConstants.Major.ERROR, minor, msg);
response = WSHelper.makeResponse(GetStatusResponse.class, r);
return response;
}
} else {
ifds.addAll(cm.getTerminals().list());
}
} catch (SCIOException ex) {
String msg = "Failed to get list with the terminals.";
LOG.warn(msg, ex);
response = WSHelper.makeResponse(GetStatusResponse.class, WSHelper.makeResultUnknownError(msg));
return response;
}
// request status for each ifd
ArrayList<IFDStatusType> status = new ArrayList<>(ifds.size());
for (SCIOTerminal ifd : ifds) {
TerminalInfo info;
try {
SingleThreadChannel channel = cm.openMasterChannel(ifd.getName());
info = new TerminalInfo(cm, channel);
} catch (NoSuchTerminal | SCIOException ex) {
// continue without a channel
info = new TerminalInfo(cm, ifd);
}
try {
IFDStatusType s = info.getStatus();
status.add(s);
} catch (SCIOException ex) {
if (ex.getCode() != SCIOErrorCode.SCARD_W_UNPOWERED_CARD && ex.getCode() != SCIOErrorCode.SCARD_W_UNRESPONSIVE_CARD && ex.getCode() != SCIOErrorCode.SCARD_W_UNSUPPORTED_CARD && ex.getCode() != SCIOErrorCode.SCARD_E_PROTO_MISMATCH) {
String msg = String.format("Failed to determine status of terminal '%s'.", ifd.getName());
LOG.warn(msg, ex);
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(GetStatusResponse.class, r);
return response;
} else {
// fall througth if there is a card which can not be connected
LOG.info("Ignoring failed status request from terminal.", ex);
}
}
}
// everything worked out well
response = WSHelper.makeResponse(GetStatusResponse.class, WSHelper.makeResultOK());
response.getIFDStatus().addAll(status);
return response;
}
Aggregations