From 6cb4a071eab9a3b8cf78b8ec7e407aa148f2d038 Mon Sep 17 00:00:00 2001 From: mcentner Date: Wed, 1 Jul 2009 13:03:41 +0000 Subject: Major refactoring of SMCC git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@381 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../java/at/gv/egiz/smcc/ccid/DefaultReader.java | 357 ++++++++++++++++++++- 1 file changed, 355 insertions(+), 2 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java') diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java b/smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java index 580b9379..682390e3 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ccid/DefaultReader.java @@ -16,16 +16,34 @@ */ package at.gv.egiz.smcc.ccid; -import at.gv.egiz.smcc.*; -import at.gv.egiz.smcc.util.SMCCHelper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.HashMap; import java.util.Map; + import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; +import javax.smartcardio.ResponseAPDU; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.ChangePINProvider; +import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINOperationAbortedException; +import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.TimeoutException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.util.ISO7816Utils; +import at.gv.egiz.smcc.util.SMCCHelper; + /** * * @author Clemens Orthacker @@ -415,4 +433,339 @@ public class DefaultReader implements CCID { } return resp; } + + + + protected byte[] createPINModifyStructure(NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) { + + ByteArrayOutputStream s = new ByteArrayOutputStream(); + // bTimeOut + s.write(getbTimeOut()); + // bTimeOut2 + s.write(getbTimeOut2()); + // bmFormatString + s.write(1 << 7 // system unit = byte + | (0xF & apduSpec.getPinPosition()) << 3 + | (0x1 & apduSpec.getPinJustification() << 2) + | (0x3 & apduSpec.getPinFormat())); + // bmPINBlockString + s.write((0xF & apduSpec.getPinLengthSize()) << 4 + | (0xF & apduSpec.getPinLength())); + // bmPINLengthFormat + s.write(// system unit = bit + (0xF & apduSpec.getPinLengthPos())); + // bInsertionOffsetOld + s.write(0x00); + // bInsertionOffsetNew + s.write(apduSpec.getPinInsertionOffsetNew()); + // wPINMaxExtraDigit + s.write(Math.min(pinSpec.getMaxLength(), getwPINMaxExtraDigitL())); + s.write(Math.max(pinSpec.getMinLength(), getwPINMaxExtraDigitH())); + // bConfirmPIN + s.write(0x01); + // bEntryValidationCondition + s.write(getbEntryValidationCondition()); + // bNumberMessage + s.write(0x02); + // wLangId + s.write(0x0C); + s.write(0x04); + // bMsgIndex1 + s.write(0x01); + // bMsgIndex2 + s.write(0x02); + // bMsgIndex3 + s.write(0x00); + + // bTeoPrologue + s.write(0x00); + s.write(0x00); + s.write(0x00); + // ulDataLength + s.write(apduSpec.getApdu().length); + s.write(0x00); + s.write(0x00); + s.write(0x00); + // abData + try { + s.write(apduSpec.getApdu()); + } catch (IOException e) { + // As we are dealing with ByteArrayOutputStreams no exception is to be + // expected. + throw new RuntimeException(e); + } + + return s.toByteArray(); + + } + + protected byte[] createPINModifyStructure(ChangeReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) { + + ByteArrayOutputStream s = new ByteArrayOutputStream(); + // bTimeOut + s.write(getbTimeOut()); + // bTimeOut2 + s.write(getbTimeOut2()); + // bmFormatString + s.write(1 << 7 // system unit = byte + | (0xF & apduSpec.getPinPosition()) << 3 + | (0x1 & apduSpec.getPinJustification() << 2) + | (0x3 & apduSpec.getPinFormat())); + // bmPINBlockString + s.write((0xF & apduSpec.getPinLengthSize()) << 4 + | (0xF & apduSpec.getPinLength())); + // bmPINLengthFormat + s.write(// system unit = bit + (0xF & apduSpec.getPinLengthPos())); + // bInsertionOffsetOld + s.write(apduSpec.getPinInsertionOffsetOld()); + // bInsertionOffsetNew + s.write(apduSpec.getPinInsertionOffsetNew()); + // wPINMaxExtraDigit + s.write(Math.min(pinSpec.getMaxLength(), getwPINMaxExtraDigitL())); + s.write(Math.max(pinSpec.getMinLength(), getwPINMaxExtraDigitH())); + // bConfirmPIN + s.write(0x03); + // bEntryValidationCondition + s.write(getbEntryValidationCondition()); + // bNumberMessage + s.write(0x03); + // wLangId + s.write(0x0C); + s.write(0x04); + // bMsgIndex1 + s.write(0x00); + // bMsgIndex2 + s.write(0x01); + // bMsgIndex3 + s.write(0x02); + + // bTeoPrologue + s.write(0x00); + s.write(0x00); + s.write(0x00); + // ulDataLength + s.write(apduSpec.getApdu().length); + s.write(0x00); + s.write(0x00); + s.write(0x00); + // abData + try { + s.write(apduSpec.getApdu()); + } catch (IOException e) { + // As we are dealing with ByteArrayOutputStreams no exception is to be + // expected. + throw new RuntimeException(e); + } + + return s.toByteArray(); + + } + + protected byte[] createPINVerifyStructure(VerifyAPDUSpec apduSpec, PINSpec pinSpec) { + + ByteArrayOutputStream s = new ByteArrayOutputStream(); + // bTimeOut + s.write(getbTimeOut()); + // bTimeOut2 + s.write(getbTimeOut2()); + // bmFormatString + s.write(1 << 7 // system unit = byte + | (0xF & apduSpec.getPinPosition()) << 3 + | (0x1 & apduSpec.getPinJustification() << 2) + | (0x3 & apduSpec.getPinFormat())); + // bmPINBlockString + s.write((0xF & apduSpec.getPinLengthSize()) << 4 + | (0xF & apduSpec.getPinLength())); + // bmPINLengthFormat + s.write(// system unit = bit + (0xF & apduSpec.getPinLengthPos())); + // wPINMaxExtraDigit + s.write(Math.min(pinSpec.getMaxLength(), getwPINMaxExtraDigitL())); // max PIN length + s.write(Math.max(pinSpec.getMinLength(), getwPINMaxExtraDigitH())); // min PIN length + // bEntryValidationCondition + s.write(getbEntryValidationCondition()); + // bNumberMessage + s.write(0xFF); + // wLangId + s.write(0x0C); + s.write(0x04); + // bMsgIndex + s.write(0x00); + // bTeoPrologue + s.write(0x00); + s.write(0x00); + s.write(0x00); + // ulDataLength + s.write(apduSpec.getApdu().length); + s.write(0x00); + s.write(0x00); + s.write(0x00); + // abData + try { + s.write(apduSpec.getApdu()); + } catch (IOException e) { + // As we are dealing with ByteArrayOutputStreams no exception is to be + // expected. + throw new RuntimeException(e); + } + + return s.toByteArray(); + + } + + @Override + public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, + PINSpec pinSpec, PINProvider provider, int retries) + throws CancelledException, InterruptedException, CardException, + SignatureCardException { + + char[] pin = provider.providePIN(pinSpec, retries); + + ResponseAPDU resp = null; + if (!disablePinpad && hasFeature(FEATURE_MODIFY_PIN_DIRECT)) { + log.debug("VERIFY using " + FEATURES[FEATURE_VERIFY_PIN_DIRECT] + "."); + byte[] s = createPINVerifyStructure(apduSpec, pinSpec); + resp = new ResponseAPDU(verifyPinDirect(s)); + } else if (!disablePinpad && hasFeature(FEATURE_VERIFY_PIN_START)) { + log.debug("VERIFY using " + FEATURES[FEATURE_MODIFY_PIN_START] + "."); + byte[] s = createPINVerifyStructure(apduSpec, pinSpec); + resp = new ResponseAPDU(verifyPin(s)); + } + + if (resp != null) { + + switch (resp.getSW()) { + + case 0x6400: + log.debug("SPE operation timed out."); + throw new TimeoutException(); + case 0x6401: + log.debug("SPE operation was cancelled by the 'Cancel' button."); + throw new CancelledException(); + case 0x6103: + log.debug("User entered too short or too long PIN " + + "regarding MIN/MAX PIN length."); + throw new PINFormatException(); + case 0x6480: + log.debug("SPE operation was aborted by the 'Cancel' operation " + + "at the host system."); + case 0x6b80: + log.info("Invalid parameter in passed structure."); + + default: + return resp; + } + + } else { + log.debug("VERIFY using software pin entry."); + return channel.transmit(ISO7816Utils.createVerifyAPDU(apduSpec, pin)); + } + + } + + @Override + public ResponseAPDU modify(CardChannel channel, + ChangeReferenceDataAPDUSpec apduSpec, PINSpec pinSpec, + ChangePINProvider provider, int retries) throws CancelledException, + InterruptedException, CardException, SignatureCardException { + + char[] oldPin = provider.provideOldPIN(pinSpec, retries); + char[] newPin = provider.providePIN(pinSpec, retries); + + ResponseAPDU resp = null; + if (!disablePinpad && hasFeature(FEATURE_MODIFY_PIN_DIRECT)) { + log.debug("MODIFY using " + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "."); + byte[] s = createPINModifyStructure(apduSpec, pinSpec); + resp = new ResponseAPDU(modifyPinDirect(s)); + } else if (!disablePinpad && hasFeature(FEATURE_MODIFY_PIN_START)) { + log.debug("MODIFY using " + FEATURES[FEATURE_MODIFY_PIN_START] + "."); + byte[] s = createPINModifyStructure(apduSpec, pinSpec); + resp = new ResponseAPDU(modifyPin(s)); + } + + if (resp != null) { + + switch (resp.getSW()) { + + case 0x6400: + log.debug("SPE operation timed out."); + throw new TimeoutException(); + case 0x6401: + log.debug("SPE operation was cancelled by the 'Cancel' button."); + throw new CancelledException(); + case 0x6103: + log.debug("User entered too short or too long PIN " + + "regarding MIN/MAX PIN length."); + throw new PINFormatException(); + case 0x6480: + log.debug("SPE operation was aborted by the 'Cancel' operation " + + "at the host system."); + case 0x6b80: + log.info("Invalid parameter in passed structure."); + + default: + return resp; + } + + } else { + log.debug("MODIFY using software pin entry."); + return channel.transmit(ISO7816Utils.createChangeReferenceDataAPDU(apduSpec, oldPin, newPin)); + } + + } + + @Override + public ResponseAPDU activate(CardChannel channel, + NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec, + PINProvider provider) throws CancelledException, + InterruptedException, CardException, SignatureCardException { + + char[] newPin = provider.providePIN(pinSpec, -1); + + ResponseAPDU resp = null; + if (!disablePinpad && hasFeature(FEATURE_MODIFY_PIN_DIRECT)) { + log.debug("MODIFY using " + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "."); + byte[] s = createPINModifyStructure(apduSpec, pinSpec); + resp = new ResponseAPDU(modifyPinDirect(s)); + } else if (!disablePinpad && hasFeature(FEATURE_MODIFY_PIN_START)) { + log.debug("MODIFY using " + FEATURES[FEATURE_MODIFY_PIN_START] + "."); + byte[] s = createPINModifyStructure(apduSpec, pinSpec); + resp = new ResponseAPDU(modifyPin(s)); + } + + if (resp != null) { + + switch (resp.getSW()) { + + case 0x6400: + log.debug("SPE operation timed out."); + throw new TimeoutException(); + case 0x6401: + log.debug("SPE operation was cancelled by the 'Cancel' button."); + throw new CancelledException(); + case 0x6103: + log.debug("User entered too short or too long PIN " + + "regarding MIN/MAX PIN length."); + throw new PINFormatException(); + case 0x6480: + log.debug("SPE operation was aborted by the 'Cancel' operation " + + "at the host system."); + case 0x6b80: + log.info("Invalid parameter in passed structure."); + + default: + return resp; + } + + } else { + log.debug("MODIFY using software pin entry."); + return channel.transmit(ISO7816Utils.createNewReferenceDataAPDU(apduSpec, newPin)); + } + + } + + + + } -- cgit v1.2.3