use of oasis.names.tc.dss._1_0.core.schema.Result in project open-ecard by ecsec.
the class AbstractTerminal method getCapabilities.
private void getCapabilities() throws IFDException {
GetIFDCapabilities capabilitiesReq = new GetIFDCapabilities();
capabilitiesReq.setContextHandle(ctxHandle);
capabilitiesReq.setIFDName(terminalInfo.getName());
GetIFDCapabilitiesResponse cap = ifd.getIFDCapabilities(capabilitiesReq);
Result r = cap.getResult();
if (r.getResultMajor().equals(ECardConstants.Major.ERROR)) {
IFDException ex = new IFDException(r);
LOG.warn(ex.getMessage(), ex);
throw ex;
}
this.capabilities = cap.getIFDCapabilities();
}
use of oasis.names.tc.dss._1_0.core.schema.Result 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;
}
}
use of oasis.names.tc.dss._1_0.core.schema.Result in project open-ecard by ecsec.
the class IFD method beginTransaction.
@Override
public BeginTransactionResponse beginTransaction(BeginTransaction beginTransaction) {
try {
BeginTransactionResponse response;
if (!hasContext()) {
String msg = "Context not initialized.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
return response;
}
try {
byte[] handle = beginTransaction.getSlotHandle();
SingleThreadChannel ch = cm.getSlaveChannel(handle);
ch.beginExclusive();
} catch (NoSuchChannel | IllegalStateException ex) {
String msg = "No card available in the requested terminal.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
LOG.warn(msg, ex);
return response;
} catch (SCIOException ex) {
String msg;
String minor;
switch(ex.getCode()) {
case SCARD_W_RESET_CARD:
case SCARD_W_REMOVED_CARD:
case SCARD_E_READER_UNAVAILABLE:
case SCARD_E_NO_SMARTCARD:
case SCARD_E_NO_SERVICE:
msg = String.format("Slot handle is not available [%s].", ex.getCode().name());
minor = ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE;
LOG.debug(msg, ex);
break;
default:
msg = "Unknown error in the underlying SCIO implementation.";
minor = ECardConstants.Minor.App.UNKNOWN_ERROR;
LOG.warn(msg, ex);
}
Result r = WSHelper.makeResultError(minor, msg);
response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
return response;
}
response = WSHelper.makeResponse(BeginTransactionResponse.class, WSHelper.makeResultOK());
return response;
} catch (Exception ex) {
LOG.warn(ex.getMessage(), ex);
throwThreadKillException(ex);
return WSHelper.makeResponse(BeginTransactionResponse.class, WSHelper.makeResult(ex));
}
}
use of oasis.names.tc.dss._1_0.core.schema.Result in project open-ecard by ecsec.
the class IFD method transmit.
@Publish
@Override
public TransmitResponse transmit(Transmit parameters) {
try {
TransmitResponse response;
if (!hasContext()) {
String msg = "Context not initialized.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(TransmitResponse.class, r);
return response;
}
try {
byte[] handle = parameters.getSlotHandle();
SingleThreadChannel ch = cm.getSlaveChannel(handle);
List<InputAPDUInfoType> apdus = parameters.getInputAPDUInfo();
// check that the apdus contain sane values
for (InputAPDUInfoType apdu : apdus) {
for (byte[] code : apdu.getAcceptableStatusCode()) {
if (code.length == 0 || code.length > 2) {
String msg = "Invalid accepted status code given.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.App.PARM_ERROR, msg);
response = WSHelper.makeResponse(TransmitResponse.class, r);
return response;
}
}
}
// transmit APDUs and stop if an error occurs or a not expected status is hit
response = WSHelper.makeResponse(TransmitResponse.class, WSHelper.makeResultOK());
Result result;
List<byte[]> rapdus = response.getOutputAPDU();
try {
for (InputAPDUInfoType capdu : apdus) {
byte[] rapdu = ch.transmit(capdu.getInputAPDU(), capdu.getAcceptableStatusCode());
rapdus.add(rapdu);
}
result = WSHelper.makeResultOK();
} catch (TransmitException ex) {
rapdus.add(ex.getResponseAPDU());
result = ex.getResult();
} catch (SCIOException ex) {
String msg = "Error during transmit.";
LOG.warn(msg, ex);
result = WSHelper.makeResultUnknownError(msg);
} catch (IllegalStateException ex) {
String msg = "Card removed during transmit.";
LOG.warn(msg, ex);
result = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
} catch (IllegalArgumentException ex) {
String msg = "Given command contains a MANAGE CHANNEL APDU.";
LOG.error(msg, ex);
result = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
}
response.setResult(result);
return response;
} catch (NoSuchChannel | IllegalStateException ex) {
String msg = "No card with transaction available in the requested terminal.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(TransmitResponse.class, r);
LOG.warn(msg, ex);
return response;
}
} catch (Exception ex) {
LOG.warn(ex.getMessage(), ex);
throwThreadKillException(ex);
return WSHelper.makeResponse(TransmitResponse.class, WSHelper.makeResult(ex));
}
}
use of oasis.names.tc.dss._1_0.core.schema.Result 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;
}
}
Aggregations