use of iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType 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 iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType 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 iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType in project open-ecard by ecsec.
the class AndroidMarshaller method parseInputAPDUInfo.
private InputAPDUInfoType parseInputAPDUInfo(XmlPullParser parser) throws XmlPullParserException, IOException {
InputAPDUInfoType inputAPDUInfo = new InputAPDUInfoType();
int eventType;
do {
parser.next();
eventType = parser.getEventType();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("InputAPDU")) {
inputAPDUInfo.setInputAPDU(StringUtils.toByteArray(parser.nextText()));
} else if (parser.getName().equals("AcceptableStatusCode")) {
inputAPDUInfo.getAcceptableStatusCode().add(StringUtils.toByteArray(parser.nextText()));
}
}
} while (!(eventType == XmlPullParser.END_TAG && parser.getName().equals("InputAPDUInfo")));
return inputAPDUInfo;
}
use of iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType in project open-ecard by ecsec.
the class PACEStep method perform.
@Override
public DIDAuthenticateResponse perform(DIDAuthenticate request, Map<String, Object> internalData) {
// get context to save values in
DynamicContext dynCtx = DynamicContext.getInstance(TR03112Keys.INSTANCE_KEY);
DIDAuthenticate didAuthenticate = request;
DIDAuthenticateResponse response = new DIDAuthenticateResponse();
ConnectionHandleType conHandle = (ConnectionHandleType) dynCtx.get(TR03112Keys.CONNECTION_HANDLE);
try {
ObjectSchemaValidator valid = (ObjectSchemaValidator) dynCtx.getPromise(EACProtocol.SCHEMA_VALIDATOR).deref();
boolean messageValid = valid.validateObject(request);
if (!messageValid) {
String msg = "Validation of the EAC1InputType message failed.";
LOG.error(msg);
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.App.INCORRECT_PARM, msg));
return response;
}
} catch (ObjectValidatorException ex) {
String msg = "Validation of the EAC1InputType message failed due to invalid input data.";
LOG.error(msg, ex);
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.App.INT_ERROR, msg));
return response;
} catch (InterruptedException ex) {
String msg = "Thread interrupted while waiting for schema validator instance.";
LOG.error(msg, ex);
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.App.INT_ERROR, msg));
return response;
}
if (!ByteUtils.compare(conHandle.getSlotHandle(), didAuthenticate.getConnectionHandle().getSlotHandle())) {
String msg = "Invalid connection handle given in DIDAuthenticate message.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.SAL.UNKNOWN_HANDLE, msg);
response.setResult(r);
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
return response;
}
byte[] slotHandle = conHandle.getSlotHandle();
dynCtx.put(EACProtocol.SLOT_HANDLE, slotHandle);
dynCtx.put(EACProtocol.DISPATCHER, dispatcher);
try {
EAC1InputType eac1Input = new EAC1InputType(didAuthenticate.getAuthenticationProtocolData());
EAC1OutputType eac1Output = eac1Input.getOutputType();
AuthenticatedAuxiliaryData aad = new AuthenticatedAuxiliaryData(eac1Input.getAuthenticatedAuxiliaryData());
byte pinID = PasswordID.valueOf(didAuthenticate.getDIDName()).getByte();
final String passwordType = PasswordID.parse(pinID).getString();
// determine PACE capabilities of the terminal
boolean nativePace = genericPACESupport(conHandle);
dynCtx.put(EACProtocol.IS_NATIVE_PACE, nativePace);
// Certificate chain
CardVerifiableCertificateChain certChain = new CardVerifiableCertificateChain(eac1Input.getCertificates());
byte[] rawCertificateDescription = eac1Input.getCertificateDescription();
CertificateDescription certDescription = CertificateDescription.getInstance(rawCertificateDescription);
// put CertificateDescription into DynamicContext which is needed for later checks
dynCtx.put(TR03112Keys.ESERVICE_CERTIFICATE_DESC, certDescription);
// according to BSI-INSTANCE_KEY-7 we MUST perform some checks immediately after receiving the eService cert
Result activationChecksResult = performChecks(certDescription, dynCtx);
if (!ECardConstants.Major.OK.equals(activationChecksResult.getResultMajor())) {
response.setResult(activationChecksResult);
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
return response;
}
CHAT requiredCHAT = new CHAT(eac1Input.getRequiredCHAT());
CHAT optionalCHAT = new CHAT(eac1Input.getOptionalCHAT());
// get the PACEMarker
CardStateEntry cardState = (CardStateEntry) internalData.get(EACConstants.IDATA_CARD_STATE_ENTRY);
PACEMarkerType paceMarker = getPaceMarker(cardState, passwordType);
dynCtx.put(EACProtocol.PACE_MARKER, paceMarker);
// Verify that the certificate description matches the terminal certificate
CardVerifiableCertificate taCert = certChain.getTerminalCertificate();
CardVerifiableCertificateVerifier.verify(taCert, certDescription);
// Verify that the required CHAT matches the terminal certificate's CHAT
CHAT taCHAT = taCert.getCHAT();
// an other role.
if (taCHAT.getRole() != CHAT.Role.AUTHENTICATION_TERMINAL) {
String msg = "Unsupported terminal type in Terminal Certificate referenced. Refernced terminal type is " + taCHAT.getRole().toString() + ".";
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.App.INCORRECT_PARM, msg));
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
return response;
}
CHATVerifier.verfiy(taCHAT, requiredCHAT);
// remove overlapping values from optional chat
optionalCHAT.restrictAccessRights(taCHAT);
// Prepare data in DIDAuthenticate for GUI
final EACData eacData = new EACData();
eacData.didRequest = didAuthenticate;
eacData.certificate = certChain.getTerminalCertificate();
eacData.certificateDescription = certDescription;
eacData.rawCertificateDescription = rawCertificateDescription;
eacData.transactionInfo = eac1Input.getTransactionInfo();
eacData.requiredCHAT = requiredCHAT;
eacData.optionalCHAT = optionalCHAT;
eacData.selectedCHAT = requiredCHAT;
eacData.aad = aad;
eacData.pinID = pinID;
eacData.passwordType = passwordType;
dynCtx.put(EACProtocol.EAC_DATA, eacData);
// get initial pin status
InputAPDUInfoType input = new InputAPDUInfoType();
input.setInputAPDU(new byte[] { (byte) 0x00, (byte) 0x22, (byte) 0xC1, (byte) 0xA4, (byte) 0x0F, (byte) 0x80, (byte) 0x0A, (byte) 0x04, (byte) 0x00, (byte) 0x7F, (byte) 0x00, (byte) 0x07, (byte) 0x02, (byte) 0x02, (byte) 0x04, (byte) 0x02, (byte) 0x02, (byte) 0x83, (byte) 0x01, (byte) 0x03 });
input.getAcceptableStatusCode().addAll(EacPinStatus.getCodes());
Transmit transmit = new Transmit();
transmit.setSlotHandle(slotHandle);
transmit.getInputAPDUInfo().add(input);
TransmitResponse pinCheckResponse = (TransmitResponse) dispatcher.safeDeliver(transmit);
WSHelper.checkResult(pinCheckResponse);
byte[] output = pinCheckResponse.getOutputAPDU().get(0);
CardResponseAPDU outputApdu = new CardResponseAPDU(output);
byte[] status = outputApdu.getStatusBytes();
dynCtx.put(EACProtocol.PIN_STATUS, EacPinStatus.fromCode(status));
// define GUI depending on the PIN status
final UserConsentDescription uc = new UserConsentDescription(LANG.translationForKey(TITLE));
final CardMonitor cardMon;
uc.setDialogType("EAC");
// create GUI and init executor
cardMon = new CardMonitor();
CardRemovedFilter filter = new CardRemovedFilter(conHandle.getIFDName(), conHandle.getSlotIndex());
eventDispatcher.add(cardMon, filter);
CVCStep cvcStep = new CVCStep(eacData);
cvcStep.setBackgroundTask(cardMon);
CVCStepAction cvcStepAction = new CVCStepAction(cvcStep);
cvcStep.setAction(cvcStepAction);
uc.getSteps().add(cvcStep);
uc.getSteps().add(CHATStep.createDummy());
uc.getSteps().add(PINStep.createDummy(passwordType));
ProcessingStep procStep = new ProcessingStep();
ProcessingStepAction procStepAction = new ProcessingStepAction(procStep);
procStep.setAction(procStepAction);
uc.getSteps().add(procStep);
Thread guiThread = new Thread(new Runnable() {
@Override
public void run() {
try {
// get context here because it is thread local
DynamicContext dynCtx = DynamicContext.getInstance(TR03112Keys.INSTANCE_KEY);
if (!uc.getSteps().isEmpty()) {
UserConsentNavigator navigator = gui.obtainNavigator(uc);
dynCtx.put(TR03112Keys.OPEN_USER_CONSENT_NAVIGATOR, navigator);
ExecutionEngine exec = new ExecutionEngine(navigator);
ResultStatus guiResult = exec.process();
dynCtx.put(EACProtocol.GUI_RESULT, guiResult);
if (guiResult == ResultStatus.CANCEL) {
Promise<Object> pPaceSuccessful = dynCtx.getPromise(EACProtocol.PACE_EXCEPTION);
if (!pPaceSuccessful.isDelivered()) {
pPaceSuccessful.deliver(WSHelper.createException(WSHelper.makeResultError(ECardConstants.Minor.SAL.CANCELLATION_BY_USER, "User canceled the PACE dialog.")));
}
}
}
} finally {
if (cardMon != null) {
eventDispatcher.del(cardMon);
}
}
}
}, "EAC-GUI");
guiThread.start();
// wait for PACE to finish
Promise<Object> pPaceException = dynCtx.getPromise(EACProtocol.PACE_EXCEPTION);
Object pPaceError = pPaceException.deref();
if (pPaceError != null) {
if (pPaceError instanceof WSHelper.WSException) {
response.setResult(((WSHelper.WSException) pPaceError).getResult());
return response;
} else if (pPaceError instanceof DispatcherException | pPaceError instanceof InvocationTargetException) {
String msg = "Internal error while PACE authentication.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.App.INT_ERROR, msg);
response.setResult(r);
return response;
} else {
String msg = "Unknown error while PACE authentication.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.App.UNKNOWN_ERROR, msg);
response.setResult(r);
return response;
}
}
// get challenge from card
TerminalAuthentication ta = new TerminalAuthentication(dispatcher, slotHandle);
byte[] challenge = ta.getChallenge();
// prepare DIDAuthenticationResponse
DIDAuthenticationDataType data = eacData.paceResponse.getAuthenticationProtocolData();
AuthDataMap paceOutputMap = new AuthDataMap(data);
// int retryCounter = Integer.valueOf(paceOutputMap.getContentAsString(PACEOutputType.RETRY_COUNTER));
byte[] efCardAccess = paceOutputMap.getContentAsBytes(PACEOutputType.EF_CARD_ACCESS);
byte[] currentCAR = paceOutputMap.getContentAsBytes(PACEOutputType.CURRENT_CAR);
byte[] previousCAR = paceOutputMap.getContentAsBytes(PACEOutputType.PREVIOUS_CAR);
byte[] idpicc = paceOutputMap.getContentAsBytes(PACEOutputType.ID_PICC);
// Store SecurityInfos
SecurityInfos securityInfos = SecurityInfos.getInstance(efCardAccess);
internalData.put(EACConstants.IDATA_SECURITY_INFOS, securityInfos);
// Store additional data
internalData.put(EACConstants.IDATA_AUTHENTICATED_AUXILIARY_DATA, aad);
internalData.put(EACConstants.IDATA_CERTIFICATES, certChain);
internalData.put(EACConstants.IDATA_CURRENT_CAR, currentCAR);
internalData.put(EACConstants.IDATA_PREVIOUS_CAR, previousCAR);
internalData.put(EACConstants.IDATA_CHALLENGE, challenge);
// Create response
// eac1Output.setRetryCounter(retryCounter);
eac1Output.setCHAT(eacData.selectedCHAT.toByteArray());
eac1Output.setCurrentCAR(currentCAR);
eac1Output.setPreviousCAR(previousCAR);
eac1Output.setEFCardAccess(efCardAccess);
eac1Output.setIDPICC(idpicc);
eac1Output.setChallenge(challenge);
response.setResult(WSHelper.makeResultOK());
response.setAuthenticationProtocolData(eac1Output.getAuthDataType());
} catch (CertificateException ex) {
LOG.error(ex.getMessage(), ex);
String msg = ex.getMessage();
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.SAL.EAC.DOC_VALID_FAILED, msg));
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
} catch (WSHelper.WSException e) {
LOG.error(e.getMessage(), e);
response.setResult(e.getResult());
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
} catch (ElementParsingException ex) {
LOG.error(ex.getMessage(), ex);
response.setResult(WSHelper.makeResultError(ECardConstants.Minor.App.INCORRECT_PARM, ex.getMessage()));
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
response.setResult(WSHelper.makeResultUnknownError(e.getMessage()));
dynCtx.put(EACProtocol.AUTHENTICATION_FAILED, true);
}
return response;
}
use of iso.std.iso_iec._24727.tech.schema.InputAPDUInfoType in project open-ecard by ecsec.
the class DIDAuthenticateStep method perform.
@Override
public DIDAuthenticateResponse perform(DIDAuthenticate request, Map<String, Object> internalData) {
DIDAuthenticateResponse response = WSHelper.makeResponse(DIDAuthenticateResponse.class, WSHelper.makeResultOK());
char[] rawPIN = null;
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
String didName = SALUtils.getDIDName(request);
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(internalData, connectionHandle);
PINCompareDIDAuthenticateInputType pinCompareInput = new PINCompareDIDAuthenticateInputType(request.getAuthenticationProtocolData());
PINCompareDIDAuthenticateOutputType pinCompareOutput = pinCompareInput.getOutputType();
byte[] cardApplication;
if (request.getDIDScope() != null && request.getDIDScope().equals(DIDScopeType.GLOBAL)) {
cardApplication = cardStateEntry.getInfo().getApplicationIdByDidName(request.getDIDName(), request.getDIDScope());
} else {
cardApplication = connectionHandle.getCardApplication();
}
Assert.securityConditionDID(cardStateEntry, cardApplication, didName, DifferentialIdentityServiceActionName.DID_AUTHENTICATE);
DIDStructureType didStructure = cardStateEntry.getDIDStructure(didName, cardApplication);
PINCompareMarkerType pinCompareMarker = new PINCompareMarkerType(didStructure.getDIDMarker());
byte keyRef = pinCompareMarker.getPINRef().getKeyRef()[0];
byte[] slotHandle = connectionHandle.getSlotHandle();
PasswordAttributesType attributes = pinCompareMarker.getPasswordAttributes();
rawPIN = pinCompareInput.getPIN();
// delete pin from memory of the structure
pinCompareInput.setPIN(null);
byte[] template = new byte[] { 0x00, 0x20, 0x00, keyRef };
byte[] responseCode;
// with [ISO7816-4] (Section 7.5.6).
if (rawPIN == null || rawPIN.length == 0) {
VerifyUser verify = new VerifyUser();
verify.setSlotHandle(slotHandle);
InputUnitType inputUnit = new InputUnitType();
verify.setInputUnit(inputUnit);
PinInputType pinInput = new PinInputType();
inputUnit.setPinInput(pinInput);
pinInput.setIndex(BigInteger.ZERO);
pinInput.setPasswordAttributes(attributes);
verify.setTemplate(template);
VerifyUserResponse verifyR = (VerifyUserResponse) dispatcher.safeDeliver(verify);
WSHelper.checkResult(verifyR);
responseCode = verifyR.getResponse();
} else {
Transmit verifyTransmit = PINUtils.buildVerifyTransmit(rawPIN, attributes, template, slotHandle);
try {
TransmitResponse transResp = (TransmitResponse) dispatcher.safeDeliver(verifyTransmit);
WSHelper.checkResult(transResp);
responseCode = transResp.getOutputAPDU().get(0);
} finally {
// blank PIN APDU
for (InputAPDUInfoType apdu : verifyTransmit.getInputAPDUInfo()) {
byte[] rawApdu = apdu.getInputAPDU();
if (rawApdu != null) {
java.util.Arrays.fill(rawApdu, (byte) 0);
}
}
}
}
CardResponseAPDU verifyResponseAPDU = new CardResponseAPDU(responseCode);
if (verifyResponseAPDU.isWarningProcessed()) {
pinCompareOutput.setRetryCounter(new BigInteger(Integer.toString((verifyResponseAPDU.getSW2() & 0x0F))));
}
cardStateEntry.addAuthenticated(didName, cardApplication);
response.setAuthenticationProtocolData(pinCompareOutput.getAuthDataType());
} catch (ECardException e) {
LOG.error(e.getMessage(), e);
response.setResult(e.getResult());
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
LOG.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
} finally {
if (rawPIN != null) {
Arrays.fill(rawPIN, ' ');
}
}
return response;
}
Aggregations