Search in sources :

Example 1 with TerminalInfo

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;
    }
}
Also used : SlotCapabilityType(iso.std.iso_iec._24727.tech.schema.SlotCapabilityType) NoSuchTerminal(org.openecard.common.ifd.scio.NoSuchTerminal) SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) SCIOException(org.openecard.common.ifd.scio.SCIOException) SCIOTerminal(org.openecard.common.ifd.scio.SCIOTerminal) DisplayCapabilityType(iso.std.iso_iec._24727.tech.schema.DisplayCapabilityType) IFDCapabilitiesType(iso.std.iso_iec._24727.tech.schema.IFDCapabilitiesType) TerminalInfo(org.openecard.ifd.scio.wrapper.TerminalInfo) Result(oasis.names.tc.dss._1_0.core.schema.Result) KeyPadCapabilityType(iso.std.iso_iec._24727.tech.schema.KeyPadCapabilityType) SCIOErrorCode(org.openecard.common.ifd.scio.SCIOErrorCode) GetIFDCapabilitiesResponse(iso.std.iso_iec._24727.tech.schema.GetIFDCapabilitiesResponse) BioSensorCapabilityType(iso.std.iso_iec._24727.tech.schema.BioSensorCapabilityType)

Example 2 with TerminalInfo

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));
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BigInteger(java.math.BigInteger) SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) TerminalInfo(org.openecard.ifd.scio.wrapper.TerminalInfo) ExecutePACEResponse(org.openecard.ifd.scio.reader.ExecutePACEResponse) ExecutePACERequest(org.openecard.ifd.scio.reader.ExecutePACERequest) DestroyChannelResponse(iso.std.iso_iec._24727.tech.schema.DestroyChannelResponse) Result(oasis.names.tc.dss._1_0.core.schema.Result)

Example 3 with TerminalInfo

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;
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BigInteger(java.math.BigInteger) ControlIFDResponse(iso.std.iso_iec._24727.tech.schema.ControlIFDResponse) SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) NoSuchChannel(org.openecard.ifd.scio.wrapper.NoSuchChannel) SCIOException(org.openecard.common.ifd.scio.SCIOException) TerminalInfo(org.openecard.ifd.scio.wrapper.TerminalInfo) Result(oasis.names.tc.dss._1_0.core.schema.Result)

Example 4 with TerminalInfo

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));
    }
}
Also used : SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) EstablishPACERequest(org.openecard.ifd.scio.reader.EstablishPACERequest) EstablishChannelResponse(iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse) DIDAuthenticationDataType(iso.std.iso_iec._24727.tech.schema.DIDAuthenticationDataType) EstablishPACEResponse(org.openecard.ifd.scio.reader.EstablishPACEResponse) TerminalInfo(org.openecard.ifd.scio.wrapper.TerminalInfo) ExecutePACEResponse(org.openecard.ifd.scio.reader.ExecutePACEResponse) ExecutePACERequest(org.openecard.ifd.scio.reader.ExecutePACERequest) Result(oasis.names.tc.dss._1_0.core.schema.Result) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BigInteger(java.math.BigInteger) ProtocolFactory(org.openecard.common.ifd.ProtocolFactory) PACEInputType(org.openecard.common.ifd.anytype.PACEInputType) PACEOutputType(org.openecard.common.ifd.anytype.PACEOutputType) Protocol(org.openecard.common.ifd.Protocol)

Example 5 with TerminalInfo

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;
}
Also used : NoSuchTerminal(org.openecard.common.ifd.scio.NoSuchTerminal) GetStatusResponse(iso.std.iso_iec._24727.tech.schema.GetStatusResponse) SCIOException(org.openecard.common.ifd.scio.SCIOException) SingleThreadChannel(org.openecard.ifd.scio.wrapper.SingleThreadChannel) SCIOTerminal(org.openecard.common.ifd.scio.SCIOTerminal) ArrayList(java.util.ArrayList) TerminalInfo(org.openecard.ifd.scio.wrapper.TerminalInfo) LinkedList(java.util.LinkedList) Result(oasis.names.tc.dss._1_0.core.schema.Result) IFDStatusType(iso.std.iso_iec._24727.tech.schema.IFDStatusType)

Aggregations

Result (oasis.names.tc.dss._1_0.core.schema.Result)5 SingleThreadChannel (org.openecard.ifd.scio.wrapper.SingleThreadChannel)5 TerminalInfo (org.openecard.ifd.scio.wrapper.TerminalInfo)5 BigInteger (java.math.BigInteger)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 SCIOException (org.openecard.common.ifd.scio.SCIOException)3 NoSuchTerminal (org.openecard.common.ifd.scio.NoSuchTerminal)2 SCIOTerminal (org.openecard.common.ifd.scio.SCIOTerminal)2 ExecutePACERequest (org.openecard.ifd.scio.reader.ExecutePACERequest)2 ExecutePACEResponse (org.openecard.ifd.scio.reader.ExecutePACEResponse)2 BioSensorCapabilityType (iso.std.iso_iec._24727.tech.schema.BioSensorCapabilityType)1 ControlIFDResponse (iso.std.iso_iec._24727.tech.schema.ControlIFDResponse)1 DIDAuthenticationDataType (iso.std.iso_iec._24727.tech.schema.DIDAuthenticationDataType)1 DestroyChannelResponse (iso.std.iso_iec._24727.tech.schema.DestroyChannelResponse)1 DisplayCapabilityType (iso.std.iso_iec._24727.tech.schema.DisplayCapabilityType)1 EstablishChannelResponse (iso.std.iso_iec._24727.tech.schema.EstablishChannelResponse)1 GetIFDCapabilitiesResponse (iso.std.iso_iec._24727.tech.schema.GetIFDCapabilitiesResponse)1 GetStatusResponse (iso.std.iso_iec._24727.tech.schema.GetStatusResponse)1 IFDCapabilitiesType (iso.std.iso_iec._24727.tech.schema.IFDCapabilitiesType)1 IFDStatusType (iso.std.iso_iec._24727.tech.schema.IFDStatusType)1