Search in sources :

Example 1 with CardResponseAPDU

use of org.openecard.common.apdu.common.CardResponseAPDU in project open-ecard by ecsec.

the class AbstractTerminal method verifyUser.

public VerifyUserResponse verifyUser(VerifyUser verify) throws SCIOException, IFDException {
    byte[] handle = verify.getSlotHandle();
    // get capabilities
    getCapabilities();
    // check if is possible to perform PinCompare protocol
    List<String> protoList = this.capabilities.getSlotCapability().get(0).getProtocol();
    if (!protoList.contains(ECardConstants.Protocol.PIN_COMPARE)) {
        throw new IFDException("PinCompare protocol is not supported by this IFD.");
    }
    // get values from requested command
    InputUnitType inputUnit = verify.getInputUnit();
    AltVUMessagesType allMsgs = getMessagesOrDefaults(verify.getAltVUMessages());
    BigInteger firstTimeout = verify.getTimeoutUntilFirstKey();
    firstTimeout = (firstTimeout == null) ? BigInteger.valueOf(60000) : firstTimeout;
    BigInteger otherTimeout = verify.getTimeoutAfterFirstKey();
    otherTimeout = (otherTimeout == null) ? BigInteger.valueOf(15000) : otherTimeout;
    final byte[] template = verify.getTemplate();
    VerifyUserResponse response;
    Result result;
    // check which type of authentication to perform
    if (inputUnit.getBiometricInput() != null) {
        // TODO: implement
        String msg = "Biometric authentication not supported by IFD.";
        IFDException ex = new IFDException(ECardConstants.Minor.IFD.IO.UNKNOWN_INPUT_UNIT, msg);
        LOG.warn(ex.getMessage(), ex);
        throw ex;
    } else if (inputUnit.getPinInput() != null) {
        final PinInputType pinInput = inputUnit.getPinInput();
        // we have a sophisticated card reader
        if (terminalInfo.supportsPinCompare()) {
            // create custom pinAction to submit pin to terminal
            NativePinStepAction pinAction = new NativePinStepAction("enter-pin", pinInput, channel, terminalInfo, template);
            // display message instructing user what to do
            UserConsentDescription uc = pinUserConsent("action.changepin.userconsent.pinstep.title", pinAction);
            UserConsentNavigator ucr = gui.obtainNavigator(uc);
            ExecutionEngine exec = new ExecutionEngine(ucr);
            // run gui
            ResultStatus status = exec.process();
            if (status == ResultStatus.CANCEL) {
                String msg = "PIN entry cancelled by user.";
                LOG.warn(msg);
                result = WSHelper.makeResultError(ECardConstants.Minor.IFD.CANCELLATION_BY_USER, msg);
                response = WSHelper.makeResponse(VerifyUserResponse.class, result);
            } else if (pinAction.exception != null) {
                LOG.warn(pinAction.exception.getMessage(), pinAction.exception);
                result = WSHelper.makeResultError(ECardConstants.Minor.IFD.AUTHENTICATION_FAILED, pinAction.exception.getMessage());
                response = WSHelper.makeResponse(VerifyUserResponse.class, result);
            } else {
                // input by user
                byte[] verifyResponse = pinAction.response;
                // evaluate result
                result = checkNativePinVerify(verifyResponse);
                response = WSHelper.makeResponse(VerifyUserResponse.class, result);
                response.setResponse(verifyResponse);
            }
            return response;
        } else if (isVirtual()) {
            // software method
            // get pin, encode and send
            int minLength = pinInput.getPasswordAttributes().getMinLength().intValue();
            int maxLength = pinInput.getPasswordAttributes().getMaxLength().intValue();
            UserConsentDescription uc = pinUserConsent("action.changepin.userconsent.pinstep.title", minLength, maxLength);
            UserConsentNavigator ucr = gui.obtainNavigator(uc);
            ExecutionEngine exec = new ExecutionEngine(ucr);
            ResultStatus status = exec.process();
            if (status == ResultStatus.CANCEL) {
                String msg = "PIN entry cancelled by user.";
                LOG.warn(msg);
                result = WSHelper.makeResultError(ECardConstants.Minor.IFD.CANCELLATION_BY_USER, msg);
                response = WSHelper.makeResponse(VerifyUserResponse.class, result);
                return response;
            }
            char[] rawPIN = getPinFromUserConsent(exec);
            PasswordAttributesType attributes = pinInput.getPasswordAttributes();
            Transmit verifyTransmit;
            try {
                verifyTransmit = PINUtils.buildVerifyTransmit(rawPIN, attributes, template, handle);
            } catch (UtilException e) {
                String msg = "Failed to create the verifyTransmit message.";
                LOG.error(msg, e);
                result = WSHelper.makeResultError(ECardConstants.Minor.IFD.UNKNOWN_ERROR, msg);
                response = WSHelper.makeResponse(VerifyUserResponse.class, result);
                return response;
            } finally {
                Arrays.fill(rawPIN, ' ');
            }
            // send to reader
            TransmitResponse transResp;
            try {
                transResp = ifd.transmit(verifyTransmit);
            } finally {
                // blank PIN APDU
                for (InputAPDUInfoType apdu : verifyTransmit.getInputAPDUInfo()) {
                    byte[] rawApdu = apdu.getInputAPDU();
                    if (rawApdu != null) {
                        Arrays.fill(rawApdu, (byte) 0);
                    }
                }
            }
            // produce messages
            if (transResp.getResult().getResultMajor().equals(ECardConstants.Major.ERROR)) {
                if (transResp.getOutputAPDU().isEmpty()) {
                    result = WSHelper.makeResultError(ECardConstants.Minor.IFD.AUTHENTICATION_FAILED, transResp.getResult().getResultMessage().getValue());
                    response = WSHelper.makeResponse(VerifyUserResponse.class, result);
                    return response;
                } else {
                    response = WSHelper.makeResponse(VerifyUserResponse.class, transResp.getResult());
                    response.setResponse(transResp.getOutputAPDU().get(0));
                    // TODO: move this code to the PIN Compare protocol
                    if (response.getResponse() != null) {
                        CardResponseAPDU resApdu = new CardResponseAPDU(response.getResponse());
                        byte[] statusBytes = resApdu.getStatusBytes();
                        boolean isMainStatus = statusBytes[0] == (byte) 0x63;
                        boolean isMinorStatus = (statusBytes[1] & (byte) 0xF0) == (byte) 0xC0;
                        int triesLeft = statusBytes[1] & 0x0F;
                        if (isMainStatus && isMinorStatus && triesLeft > 0) {
                            LOG.info("PIN not entered successful. There are {} tries left.", statusBytes[1] & 0x0F);
                            return verifyUser(verify);
                        }
                    }
                    return response;
                }
            } else {
                response = WSHelper.makeResponse(VerifyUserResponse.class, transResp.getResult());
                response.setResponse(transResp.getOutputAPDU().get(0));
                return response;
            }
        } else {
            IFDException ex = new IFDException("No input unit available to perform PinCompare protocol.");
            LOG.warn(ex.getMessage(), ex);
            throw ex;
        }
    } else {
        String msg = "Unsupported authentication input method requested.";
        IFDException ex = new IFDException(ECardConstants.Minor.IFD.IO.UNKNOWN_INPUT_UNIT, msg);
        LOG.warn(ex.getMessage(), ex);
        throw ex;
    }
}
Also used : Transmit(iso.std.iso_iec._24727.tech.schema.Transmit) PasswordAttributesType(iso.std.iso_iec._24727.tech.schema.PasswordAttributesType) ResultStatus(org.openecard.gui.ResultStatus) AltVUMessagesType(iso.std.iso_iec._24727.tech.schema.AltVUMessagesType) VerifyUserResponse(iso.std.iso_iec._24727.tech.schema.VerifyUserResponse) UtilException(org.openecard.common.util.UtilException) InputAPDUInfoType(iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType) UserConsentNavigator(org.openecard.gui.UserConsentNavigator) Result(oasis.names.tc.dss._1_0.core.schema.Result) InputUnitType(iso.std.iso_iec._24727.tech.schema.InputUnitType) ExecutionEngine(org.openecard.gui.executor.ExecutionEngine) UserConsentDescription(org.openecard.gui.definition.UserConsentDescription) BigInteger(java.math.BigInteger) TransmitResponse(iso.std.iso_iec._24727.tech.schema.TransmitResponse) CardResponseAPDU(org.openecard.common.apdu.common.CardResponseAPDU) PinInputType(iso.std.iso_iec._24727.tech.schema.PinInputType)

Example 2 with CardResponseAPDU

use of org.openecard.common.apdu.common.CardResponseAPDU in project open-ecard by ecsec.

the class SingleThreadChannel method transmit.

@Nonnull
@Override
public byte[] transmit(@Nonnull byte[] input, @Nonnull List<byte[]> responses) throws TransmitException, SCIOException, IllegalStateException {
    byte[] inputAPDU = input;
    if (isSM()) {
        LOG.debug("Apply secure messaging to APDU: {}", ByteUtils.toHexString(inputAPDU, true));
        inputAPDU = smProtocol.applySM(inputAPDU);
    }
    LOG.debug("Send APDU: {}", ByteUtils.toHexString(inputAPDU, true));
    CardResponseAPDU rapdu = transmit(inputAPDU);
    byte[] result = rapdu.toByteArray();
    LOG.debug("Receive APDU: {}", ByteUtils.toHexString(result, true));
    if (isSM()) {
        result = smProtocol.removeSM(result);
        LOG.debug("Remove secure messaging from APDU: {}", ByteUtils.toHexString(result, true));
    }
    // get status word
    byte[] sw = new byte[2];
    sw[0] = result[result.length - 2];
    sw[1] = result[result.length - 1];
    // return without validation when no expected results given
    if (responses.isEmpty()) {
        return result;
    }
    // verify result
    for (byte[] expected : responses) {
        // AcceptableStatusCode-elements containing only one byte match all status codes starting with this byte
        if (ByteUtils.isPrefix(expected, sw)) {
            return result;
        }
    }
    // not an expected result
    String msg = "The returned status code is not in the list of expected status codes. The returned code is:\n";
    TransmitException tex = new TransmitException(result, msg + CardCommandStatus.getMessage(sw));
    throw tex;
}
Also used : TransmitException(org.openecard.ifd.scio.TransmitException) CardResponseAPDU(org.openecard.common.apdu.common.CardResponseAPDU) Nonnull(javax.annotation.Nonnull)

Example 3 with CardResponseAPDU

use of org.openecard.common.apdu.common.CardResponseAPDU in project open-ecard by ecsec.

the class NFCCardChannel method transmit.

@Override
public int transmit(ByteBuffer command, ByteBuffer response) throws SCIOException {
    CardResponseAPDU cra = transmit(command.array());
    byte[] data = cra.toByteArray();
    response.put(data);
    return data.length;
}
Also used : CardResponseAPDU(org.openecard.common.apdu.common.CardResponseAPDU)

Example 4 with CardResponseAPDU

use of org.openecard.common.apdu.common.CardResponseAPDU in project open-ecard by ecsec.

the class TinySAL method dataSetSelect.

/**
 * The DataSetSelect function selects a data set in a card application.
 * See BSI-TR-03112-4, version 1.1.2, section 3.4.3.
 *
 * @param request DataSetSelect
 * @return DataSetSelectResponse
 */
@Publish
@Override
public DataSetSelectResponse dataSetSelect(DataSetSelect request) {
    DataSetSelectResponse response = WSHelper.makeResponse(DataSetSelectResponse.class, WSHelper.makeResultOK());
    try {
        ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
        CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(states, connectionHandle);
        byte[] applicationID = connectionHandle.getCardApplication();
        String dataSetName = request.getDataSetName();
        Assert.assertIncorrectParameter(dataSetName, "The parameter DataSetName is empty.");
        CardInfoWrapper cardInfoWrapper = cardStateEntry.getInfo();
        DataSetInfoType dataSetInfo = cardInfoWrapper.getDataSet(dataSetName, applicationID);
        Assert.assertNamedEntityNotFound(dataSetInfo, "The given DataSet cannot be found.");
        Assert.securityConditionDataSet(cardStateEntry, applicationID, dataSetName, NamedDataServiceActionName.DATA_SET_SELECT);
        byte[] fileID = dataSetInfo.getDataSetPath().getEfIdOrPath();
        byte[] slotHandle = connectionHandle.getSlotHandle();
        CardResponseAPDU result = CardUtils.selectFileWithOptions(env.getDispatcher(), slotHandle, fileID, null, CardUtils.FCP_RESPONSE_DATA);
        FCP fcp = null;
        if (result != null && result.getData().length > 0) {
            try {
                fcp = new FCP(result.getData());
            } catch (TLVException ex) {
                LOG.warn("Invalid FCP received.");
            }
        }
        if (fcp == null) {
            LOG.info("Using fake FCP.");
            fcp = new FCP(createFakeFCP(Arrays.copyOfRange(fileID, fileID.length - 2, fileID.length)));
        }
        cardStateEntry.setFCPOfSelectedEF(fcp);
    } catch (ECardException e) {
        response.setResult(e.getResult());
    } catch (Exception e) {
        LOG.error(e.getMessage(), e);
        throwThreadKillException(e);
        response.setResult(WSHelper.makeResult(e));
    }
    return response;
}
Also used : ConnectionHandleType(iso.std.iso_iec._24727.tech.schema.ConnectionHandleType) ECardException(org.openecard.common.ECardException) CardStateEntry(org.openecard.common.sal.state.CardStateEntry) FCP(org.openecard.common.tlv.iso7816.FCP) CardInfoWrapper(org.openecard.common.sal.state.cif.CardInfoWrapper) DataSetInfoType(iso.std.iso_iec._24727.tech.schema.DataSetInfoType) CardResponseAPDU(org.openecard.common.apdu.common.CardResponseAPDU) TLVException(org.openecard.common.tlv.TLVException) PrerequisitesNotSatisfiedException(org.openecard.common.sal.exception.PrerequisitesNotSatisfiedException) NameExistsException(org.openecard.common.sal.exception.NameExistsException) AddonNotFoundException(org.openecard.addon.AddonNotFoundException) ThreadTerminateException(org.openecard.common.ThreadTerminateException) ECardException(org.openecard.common.ECardException) NamedEntityNotFoundException(org.openecard.common.sal.exception.NamedEntityNotFoundException) UnknownProtocolException(org.openecard.common.sal.exception.UnknownProtocolException) IncorrectParameterException(org.openecard.common.sal.exception.IncorrectParameterException) InappropriateProtocolForActionException(org.openecard.common.sal.exception.InappropriateProtocolForActionException) TLVException(org.openecard.common.tlv.TLVException) SecurityConditionNotSatisfiedException(org.openecard.common.sal.exception.SecurityConditionNotSatisfiedException) UnknownConnectionHandleException(org.openecard.common.sal.exception.UnknownConnectionHandleException) DataSetSelectResponse(iso.std.iso_iec._24727.tech.schema.DataSetSelectResponse) Publish(org.openecard.common.interfaces.Publish)

Example 5 with CardResponseAPDU

use of org.openecard.common.apdu.common.CardResponseAPDU in project open-ecard by ecsec.

the class TinySAL method cardApplicationConnect.

/**
 * The CardApplicationConnect function establishes an unauthenticated connection between the client
 * application and the card application.
 * See BSI-TR-03112-4, version 1.1.2, section 3.2.1.
 *
 * @param request CardApplicationConnect
 * @return CardApplicationConnectResponse
 */
@Override
public CardApplicationConnectResponse cardApplicationConnect(CardApplicationConnect request) {
    CardApplicationConnectResponse response = WSHelper.makeResponse(CardApplicationConnectResponse.class, WSHelper.makeResultOK());
    try {
        CardApplicationPathType cardAppPath = request.getCardApplicationPath();
        Assert.assertIncorrectParameter(cardAppPath, "The parameter CardAppPathRequest is empty.");
        Set<CardStateEntry> cardStateEntrySet = states.getMatchingEntries(cardAppPath, false);
        Assert.assertIncorrectParameter(cardStateEntrySet, "The given ConnectionHandle is invalid.");
        /*
	     * [TR-03112-4] If the provided path fragments are valid for more than one card application
	     * the eCard-API-Framework SHALL return any of the possible choices.
	     */
        CardStateEntry cardStateEntry = cardStateEntrySet.iterator().next();
        byte[] applicationID = cardAppPath.getCardApplication();
        if (applicationID == null) {
            if (cardStateEntry.getImplicitlySelectedApplicationIdentifier() != null) {
                applicationID = cardStateEntry.getImplicitlySelectedApplicationIdentifier();
            } else {
                applicationID = MF;
            }
        }
        Assert.securityConditionApplication(cardStateEntry, applicationID, ConnectionServiceActionName.CARD_APPLICATION_CONNECT);
        // Connect to the card
        ConnectionHandleType handle = cardStateEntry.handleCopy();
        cardStateEntry = cardStateEntry.derive(handle);
        Connect connect = new Connect();
        connect.setContextHandle(handle.getContextHandle());
        connect.setIFDName(handle.getIFDName());
        connect.setSlot(handle.getSlotIndex());
        ConnectResponse connectResponse = (ConnectResponse) env.getDispatcher().safeDeliver(connect);
        WSHelper.checkResult(connectResponse);
        // Select the card application
        CardCommandAPDU select;
        // TODO: proper determination of path, file and app id
        if (applicationID.length == 2) {
            select = new Select.File(applicationID);
            List<byte[]> responses = new ArrayList<>();
            responses.add(TrailerConstants.Success.OK());
            responses.add(TrailerConstants.Error.WRONG_P1_P2());
            CardResponseAPDU resp = select.transmit(env.getDispatcher(), connectResponse.getSlotHandle(), responses);
            if (Arrays.equals(resp.getTrailer(), TrailerConstants.Error.WRONG_P1_P2())) {
                select = new Select.AbsolutePath(applicationID);
                select.transmit(env.getDispatcher(), connectResponse.getSlotHandle());
            }
        } else {
            select = new Select.Application(applicationID);
            select.transmit(env.getDispatcher(), connectResponse.getSlotHandle());
        }
        cardStateEntry.setCurrentCardApplication(applicationID);
        cardStateEntry.setSlotHandle(connectResponse.getSlotHandle());
        // reset the ef FCP
        cardStateEntry.unsetFCPOfSelectedEF();
        states.addEntry(cardStateEntry);
        response.setConnectionHandle(cardStateEntry.handleCopy());
        response.getConnectionHandle().setCardApplication(applicationID);
    } catch (ECardException e) {
        response.setResult(e.getResult());
    }
    return response;
}
Also used : ConnectionHandleType(iso.std.iso_iec._24727.tech.schema.ConnectionHandleType) CardCommandAPDU(org.openecard.common.apdu.common.CardCommandAPDU) CardStateEntry(org.openecard.common.sal.state.CardStateEntry) ConnectResponse(iso.std.iso_iec._24727.tech.schema.ConnectResponse) CardApplicationConnectResponse(iso.std.iso_iec._24727.tech.schema.CardApplicationConnectResponse) CardApplicationConnect(iso.std.iso_iec._24727.tech.schema.CardApplicationConnect) Connect(iso.std.iso_iec._24727.tech.schema.Connect) ArrayList(java.util.ArrayList) CardApplicationConnectResponse(iso.std.iso_iec._24727.tech.schema.CardApplicationConnectResponse) CardApplicationPathType(iso.std.iso_iec._24727.tech.schema.CardApplicationPathType) ECardException(org.openecard.common.ECardException) Select(org.openecard.common.apdu.Select) CardApplicationSelect(iso.std.iso_iec._24727.tech.schema.CardApplicationSelect) DataSetSelect(iso.std.iso_iec._24727.tech.schema.DataSetSelect) CardResponseAPDU(org.openecard.common.apdu.common.CardResponseAPDU)

Aggregations

CardResponseAPDU (org.openecard.common.apdu.common.CardResponseAPDU)24 CardCommandAPDU (org.openecard.common.apdu.common.CardCommandAPDU)9 ConnectionHandleType (iso.std.iso_iec._24727.tech.schema.ConnectionHandleType)7 CardStateEntry (org.openecard.common.sal.state.CardStateEntry)7 ECardException (org.openecard.common.ECardException)6 APDUException (org.openecard.common.apdu.exception.APDUException)6 Select (org.openecard.common.apdu.Select)5 TLVException (org.openecard.common.tlv.TLVException)4 FCP (org.openecard.common.tlv.iso7816.FCP)4 InputAPDUInfoType (iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType)3 Transmit (iso.std.iso_iec._24727.tech.schema.Transmit)3 TransmitResponse (iso.std.iso_iec._24727.tech.schema.TransmitResponse)3 BigInteger (java.math.BigInteger)3 ArrayList (java.util.ArrayList)3 CardApplicationPathType (iso.std.iso_iec._24727.tech.schema.CardApplicationPathType)2 CardApplicationSelect (iso.std.iso_iec._24727.tech.schema.CardApplicationSelect)2 DIDAuthenticateResponse (iso.std.iso_iec._24727.tech.schema.DIDAuthenticateResponse)2 DIDStructureType (iso.std.iso_iec._24727.tech.schema.DIDStructureType)2 DataSetInfoType (iso.std.iso_iec._24727.tech.schema.DataSetInfoType)2 DataSetSelect (iso.std.iso_iec._24727.tech.schema.DataSetSelect)2