diff options
Diffstat (limited to 'smcc')
50 files changed, 2262 insertions, 609 deletions
| diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index 1ed5a177..b8cdb208 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -16,6 +16,8 @@  */  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream; @@ -79,10 +81,16 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    public static final byte KID_PIN_SIG = (byte) 0x81; +  public static final byte KID_PUK_SIG = (byte) 0x83; +    public static final byte KID_PIN_DEC = (byte) 0x81; +  public static final byte KID_PUK_DEC = (byte) 0x82; +    public static final byte KID_PIN_INF = (byte) 0x83; +  public static final byte KID_PUK_INF = (byte) 0x84; +    public static final byte[] DST_SIG = new byte[] { (byte) 0x84, (byte) 0x01, // tag        // ,        // length @@ -217,7 +225,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    @Override    @Exclusive -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      if ("IdentityLink".equals(infobox)) { @@ -233,7 +241,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    } -  protected byte[] getIdentityLinkV1(PINProvider provider, String domainId)  +  protected byte[] getIdentityLinkV1(PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      try { @@ -262,7 +270,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    } -  protected byte[] getIdentityLinkV2(PINProvider provider, String domainId) +  protected byte[] getIdentityLinkV2(PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      try { @@ -388,7 +396,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    @Override    @Exclusive    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +      PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException {      ByteArrayOutputStream dst = new ByteArrayOutputStream();      // key ID @@ -487,7 +495,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC     * @see at.gv.egiz.smcc.AbstractSignatureCard#verifyPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider)     */    @Override -  public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) +  public void verifyPIN(PINSpec pinSpec, PINGUI pinProvider)        throws LockedException, NotActivatedException, CancelledException,        TimeoutException, SignatureCardException, InterruptedException { @@ -509,7 +517,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC     * @see at.gv.egiz.smcc.AbstractSignatureCard#changePIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.ChangePINProvider)     */    @Override -  public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) +  public void changePIN(PINSpec pinSpec, ModifyPINGUI pinProvider)        throws LockedException, NotActivatedException, CancelledException,        TimeoutException, SignatureCardException, InterruptedException { @@ -528,7 +536,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    }    @Override -  public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) +  public void activatePIN(PINSpec pinSpec, ModifyPINGUI pinGUI)        throws CancelledException, SignatureCardException, CancelledException,        TimeoutException, InterruptedException {      log.error("ACTIVATE PIN not supported by ACOS"); @@ -536,7 +544,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    }    @Override -  public void unblockPIN(PINSpec pinSpec, PINProvider pinProvider) +  public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pinGUI)        throws CancelledException, SignatureCardException, InterruptedException {      throw new SignatureCardException("Unblock PIN not supported.");    } @@ -570,10 +578,8 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    // PROTECTED METHODS (assume exclusive card access)    //////////////////////////////////////////////////////////////////////// -  protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINProvider provider) -      throws InterruptedException, LockedException, NotActivatedException, -      TimeoutException, PINFormatException, PINOperationAbortedException, -      SignatureCardException, CardException { +  protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINGUI provider) +      throws InterruptedException, CardException, SignatureCardException {      int retries = -1;      do { @@ -581,10 +587,8 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC      } while (retries > 0);    } -  protected void changePINLoop(CardChannel channel, PINSpec spec, ChangePINProvider provider) -      throws InterruptedException, LockedException, NotActivatedException, -      TimeoutException, PINFormatException, PINOperationAbortedException, -      SignatureCardException, CardException { +  protected void changePINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider) +      throws InterruptedException, CardException, SignatureCardException {      int retries = -1;      do { @@ -593,7 +597,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    }    protected int verifyPIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider, int retries) throws InterruptedException, CardException, SignatureCardException { +      PINGUI provider, int retries) throws InterruptedException, CardException, SignatureCardException {      VerifyAPDUSpec apduSpec = new VerifyAPDUSpec(          new byte[] { @@ -602,7 +606,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC              (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 },           0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); -    ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +    ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);      if (resp.getSW() == 0x9000) {        return -1; @@ -625,7 +629,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    }    protected int changePIN(CardChannel channel, PINSpec pinSpec, -      ChangePINProvider pinProvider, int retries) throws CancelledException, InterruptedException, CardException, SignatureCardException { +      ModifyPINGUI pinProvider, int retries) throws CancelledException, InterruptedException, CardException, SignatureCardException {      ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec(          new byte[] { @@ -639,7 +643,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC -    ResponseAPDU resp = reader.modify(channel, apduSpec, pinSpec, pinProvider, retries); +    ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinSpec, retries);      if (resp.getSW() == 0x9000) {        return -1; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index 54b4c7fe..fcb94fc6 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -16,6 +16,8 @@  */  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.reader.CardReader; +import at.gv.egiz.smcc.reader.ReaderFactory;  import java.util.ArrayList;  import java.util.List;  import java.util.Locale; @@ -29,9 +31,6 @@ import javax.smartcardio.CardTerminal;  import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory; -import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.ccid.ReaderFactory; -  public abstract class AbstractSignatureCard implements SignatureCard {    private static Log log = LogFactory.getLog(AbstractSignatureCard.class); @@ -45,7 +44,7 @@ public abstract class AbstractSignatureCard implements SignatureCard {    private Card card_; -  protected CCID reader; +  protected CardReader reader;    protected AbstractSignatureCard(String resourceBundleName) {      this.resourceBundleName = resourceBundleName; @@ -68,7 +67,7 @@ public abstract class AbstractSignatureCard implements SignatureCard {    @Override    public void init(Card card, CardTerminal cardTerminal) {      this.card_ = card; -    this.reader = ReaderFactory.getInstance().getReader(card, cardTerminal); +    this.reader = ReaderFactory.getReader(card, cardTerminal);    }    @Override @@ -81,11 +80,6 @@ public abstract class AbstractSignatureCard implements SignatureCard {    }    @Override -  public CCID getReader() { -    return reader; -  } - -  @Override    public void setLocale(Locale locale) {      if (locale == null) {        throw new NullPointerException("Locale must not be set to null"); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java index e02a55d4..41358bb5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java @@ -18,6 +18,7 @@  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.IOException;  import java.io.InputStream;  import java.security.MessageDigest; @@ -110,7 +111,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {    @Override    @Exclusive -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      throw new IllegalArgumentException("Infobox '" + infobox @@ -120,7 +121,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {    @Override    @Exclusive    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +      PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException {      if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) {        throw new SignatureCardException("Card does not support key " + keyboxName + "."); @@ -176,7 +177,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {    }    protected void verifyPINLoop(CardChannel channel, PINSpec spec, -      PINProvider provider) throws LockedException, NotActivatedException, +      PINGUI provider) throws LockedException, NotActivatedException,        SignatureCardException, InterruptedException, CardException {      int retries = -1; //verifyPIN(channel, spec, null, -1); @@ -186,7 +187,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {    }    protected int verifyPIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider, int retries) throws SignatureCardException, +      PINGUI provider, int retries) throws SignatureCardException,        LockedException, NotActivatedException, InterruptedException,        CardException { @@ -197,7 +198,7 @@ public class BELPICCard extends AbstractSignatureCard implements SignatureCard {              (byte) 0xff, (byte) 0xff, (byte) 0xff },           1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); -    ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +    ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);      if (resp.getSW() == 0x9000) {        return -1; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java index 831a1f9b..64389190 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java @@ -17,6 +17,7 @@  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream; @@ -96,7 +97,7 @@ public class ITCard extends AbstractSignatureCard {    @Override    @Exclusive -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI provider, String domainId)        throws SignatureCardException, InterruptedException {      throw new IllegalArgumentException("Infobox '" + infobox @@ -106,7 +107,7 @@ public class ITCard extends AbstractSignatureCard {    @Override    @Exclusive    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, +      PINGUI provider, String alg) throws SignatureCardException,        InterruptedException, IOException {      if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { @@ -159,7 +160,7 @@ public class ITCard extends AbstractSignatureCard {    }    protected void verifyPINLoop(CardChannel channel, PINSpec spec, -      PINProvider provider) throws LockedException, NotActivatedException, +      PINGUI provider) throws LockedException, NotActivatedException,        SignatureCardException, InterruptedException, CardException {      int retries = -1; @@ -169,7 +170,7 @@ public class ITCard extends AbstractSignatureCard {    }    protected int verifyPIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider, int retries) throws SignatureCardException, +      PINGUI provider, int retries) throws SignatureCardException,        LockedException, NotActivatedException, InterruptedException,        CardException { @@ -180,7 +181,7 @@ public class ITCard extends AbstractSignatureCard {              (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff },           0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); -    ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +    ResponseAPDU resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);      if (resp.getSW() == 0x9000) {        return -2; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java index eaf38435..24dfa53c 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINConfirmationException.java @@ -23,23 +23,4 @@ package at.gv.egiz.smcc;   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */  public class PINConfirmationException extends SignatureCardException { - -  private static final long serialVersionUID = 1L; - -  public PINConfirmationException() { -    super(); -  } - -  public PINConfirmationException(String message, Throwable cause) { -    super(message, cause); -  } - -  public PINConfirmationException(String message) { -    super(message); -  } - -  public PINConfirmationException(Throwable cause) { -    super(cause); -  } -  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java index 774fcdf5..721c63e2 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINFormatException.java @@ -23,23 +23,4 @@ package at.gv.egiz.smcc;   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */  public class PINFormatException extends SignatureCardException { - -  private static final long serialVersionUID = 1L; - -  public PINFormatException() { -    super(); -  } - -  public PINFormatException(String message, Throwable cause) { -    super(message, cause); -  } - -  public PINFormatException(String message) { -    super(message); -  } - -  public PINFormatException(Throwable cause) { -    super(cause); -  } -  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java index 53738612..5091c10f 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINMgmtSignatureCard.java @@ -16,6 +16,9 @@  */  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; + +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.util.List;  public interface PINMgmtSignatureCard extends SignatureCard { @@ -26,16 +29,16 @@ public interface PINMgmtSignatureCard extends SignatureCard {    public PIN_STATE getPINState(PINSpec pinSpec) throws SignatureCardException; -  public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) +  public void verifyPIN(PINSpec pinSpec, PINGUI pinGUI)    throws LockedException, NotActivatedException, CancelledException, SignatureCardException, InterruptedException; -  public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) +  public void changePIN(PINSpec pinSpec, ModifyPINGUI changePINGUI)    throws LockedException, NotActivatedException, CancelledException, PINFormatException, SignatureCardException, InterruptedException; -  public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) +  public void activatePIN(PINSpec pinSpec, ModifyPINGUI activatePINGUI)    throws CancelledException, SignatureCardException, InterruptedException; -  public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) +  public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pukGUI)    throws CancelledException, SignatureCardException, InterruptedException;  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java b/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java new file mode 100644 index 00000000..7e71eb7e --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ResetRetryCounterAPDUSpec.java @@ -0,0 +1,38 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.smcc; + +public class ResetRetryCounterAPDUSpec extends ChangeReferenceDataAPDUSpec { + +  /** +   * @param apdu +   * @param pukPosition +   * @param pukFormat +   * @param pukLength +   * @param pukLengthSize +   * @param pukLengthPos +   * @param pinInsertionOffsetNew +   */ +  public ResetRetryCounterAPDUSpec(byte[] apdu, int pukPosition, +      int pukFormat, int pukLength, int pukLengthSize, int pukLengthPos, +      int pinInsertionOffsetNew) { +    super(apdu, pukPosition, pukFormat, pukLength, pukLengthSize, pukLengthPos); +    this.pinInsertionOffsetNew = pinInsertionOffsetNew; +  } + +   +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java index 79a4cc69..ad05352f 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -17,6 +17,8 @@  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream; @@ -225,7 +227,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    @Override    @Exclusive -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI pinGUI, String domainId)        throws SignatureCardException, InterruptedException {      try { @@ -243,7 +245,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu            try {              return ISO7816Utils.readTransparentFileTLV(channel, -1, (byte) 0x30);            } catch (SecurityStatusNotSatisfiedException e) { -            verifyPINLoop(channel, spec, provider); +            verifyPINLoop(channel, spec, pinGUI);            }          } @@ -301,7 +303,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    @Override    @Exclusive    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +      PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException {      ByteArrayOutputStream dst = new ByteArrayOutputStream();      byte[] ht = null; @@ -431,7 +433,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu     */    @Override    @Exclusive -  public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) +  public void verifyPIN(PINSpec pinSpec, PINGUI pinProvider)        throws LockedException, NotActivatedException, CancelledException,        TimeoutException, SignatureCardException, InterruptedException { @@ -442,12 +444,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu          // SELECT application          execSELECT_AID(channel, pinSpec.getContextAID());        } -      log.debug("*** verifyPIN loop");        verifyPINLoop(channel, pinSpec, pinProvider); -//      log.debug("*** verifyPIN 0"); -//      int retries = verifyPIN(channel, pinSpec, null, 0); -//      log.debug("*** verifyPIN " + retries + " tries"); -//      verifyPIN(channel, pinSpec, pinProvider, retries);      } catch (CardException e) {        log.info("Failed to verify PIN.", e);        throw new SignatureCardException("Failed to verify PIN.", e); @@ -460,7 +457,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu     */    @Override    @Exclusive -  public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) +  public void changePIN(PINSpec pinSpec, ModifyPINGUI pinGUI)        throws LockedException, NotActivatedException, CancelledException,        TimeoutException, SignatureCardException, InterruptedException { @@ -471,9 +468,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu          // SELECT application          execSELECT_AID(channel, pinSpec.getContextAID());        } -      changePINLoop(channel, pinSpec, pinProvider); -//      int retries = verifyPIN(channel, pinSpec, null, 0); -//      changePIN(channel, pinSpec, pinProvider, retries); +      changePINLoop(channel, pinSpec, pinGUI);      } catch (CardException e) {        log.info("Failed to change PIN.", e);        throw new SignatureCardException("Failed to change PIN.", e); @@ -486,7 +481,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu     */    @Override    @Exclusive -  public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) +  public void activatePIN(PINSpec pinSpec, ModifyPINGUI activatePINGUI)        throws CancelledException, SignatureCardException, CancelledException,        TimeoutException, InterruptedException { @@ -497,7 +492,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu          // SELECT application          execSELECT_AID(channel, pinSpec.getContextAID());        } -      activatePIN(channel, pinSpec, pinProvider); +      activatePIN(channel, pinSpec, activatePINGUI);      } catch (CardException e) {        log.info("Failed to activate PIN.", e);        throw new SignatureCardException("Failed to activate PIN.", e); @@ -509,9 +504,16 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu     * @see at.gv.egiz.smcc.PINMgmtSignatureCard#unblockPIN(at.gv.egiz.smcc.PINSpec, at.gv.egiz.smcc.PINProvider)     */    @Override -  public void unblockPIN(PINSpec pinSpec, PINProvider pukProvider) +  public void unblockPIN(PINSpec pinSpec, ModifyPINGUI pukProvider)        throws CancelledException, SignatureCardException, InterruptedException { -    throw new SignatureCardException("Unblock PIN is not supported."); +    CardChannel channel = getCardChannel(); + +    try { +      unblockPINLoop(channel, pinSpec, pukProvider); +    } catch (CardException e) { +      log.info("Failed to activate PIN.", e); +      throw new SignatureCardException("Failed to activate PIN.", e); +    }    }    @Override @@ -574,7 +576,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    // PROTECTED METHODS (assume exclusive card access)    //////////////////////////////////////////////////////////////////////// -  protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINProvider provider) +  protected void verifyPINLoop(CardChannel channel, PINSpec spec, PINGUI provider)        throws LockedException, NotActivatedException, SignatureCardException,        InterruptedException, CardException { @@ -584,7 +586,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      } while (retries > 0);    } -  protected void changePINLoop(CardChannel channel, PINSpec spec, ChangePINProvider provider) +  protected void changePINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider)        throws LockedException, NotActivatedException, SignatureCardException,        InterruptedException, CardException { @@ -594,8 +596,19 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      } while (retries > 0);    } +  protected void unblockPINLoop(CardChannel channel, PINSpec spec, ModifyPINGUI provider) +      throws LockedException, NotActivatedException, SignatureCardException, +      InterruptedException, CardException { + +    //TODO get PUK retry counter from EF FID 0036 in MF +    int retries = -1; +    do { +      retries = unblockPIN(channel, spec, provider, retries); +    } while (retries > 0); +  } +    protected int verifyPIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider, int retries) throws SignatureCardException, +      PINGUI provider, int retries) throws SignatureCardException,        LockedException, NotActivatedException, InterruptedException,        CardException { @@ -608,108 +621,135 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      ResponseAPDU resp;      if (provider != null) { -      resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +      resp = reader.verify(channel, apduSpec, provider, pinSpec, retries);      } else {        resp = channel.transmit(new CommandAPDU(0x00, 0x20, 0x00, pinSpec.getKID()));      } -     + +      if (resp.getSW() == 0x9000) {        return -1; -    } -    if (resp.getSW() == 0x63c0) { -      // returned by the 'short' VERIFY +    } else if (resp.getSW() == 0x6983 || resp.getSW() == 0x63c0) { +      // authentication method blocked (0x63c0 returned by 'short' VERIFY)        throw new LockedException(); -    } -    if (resp.getSW() >> 4 == 0x63c) { -      return 0x0f & resp.getSW(); -    } -     -    switch (resp.getSW()) { -    case 0x6983: -      // authentication method blocked -      // returned by the 'long' VERIFY -      throw new LockedException(); -    case 0x6984: -      // reference data not usable +    } else if (resp.getSW() == 0x6984 || resp.getSW() == 0x6985) { +      // reference data not usable; conditions of use not satisfied        throw new NotActivatedException(); -    case 0x6985: -      // conditions of use not satisfied +    } else if (resp.getSW() >> 4 == 0x63c) { +      return 0x0f & resp.getSW(); +    } else if (version > 1.2 && resp.getSW() == 0x6400) { +      log.warn("cannot query pin status prior to card activation");        throw new NotActivatedException(); -   -    default: +    } else {        String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW());         log.info(msg);        throw new SignatureCardException(msg);      } -        }    protected int changePIN(CardChannel channel, PINSpec pinSpec, -      ChangePINProvider pinProvider, int retries) throws CancelledException, +      ModifyPINGUI pinProvider, int retries) throws CancelledException,        InterruptedException, CardException, SignatureCardException { -     -    ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec( -        new byte[] {  -            (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10,  -            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,  -            (byte) 0xff, (byte) 0xff, (byte) 0xff,  -            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,  -            (byte) 0xff, (byte) 0xff, (byte) 0xff },  + +      ChangeReferenceDataAPDUSpec apduSpec = new ChangeReferenceDataAPDUSpec( +        new byte[] { +            (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10, +            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0xff, (byte) 0xff, (byte) 0xff },          1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4, 8); -     -    ResponseAPDU resp = reader.modify(channel, apduSpec, pinSpec, pinProvider, retries); -     + +    ResponseAPDU resp = reader.modify(channel, apduSpec, pinProvider, pinSpec, retries); +      if (resp.getSW() == 0x9000) {        return -1; -    } -    if (resp.getSW() >> 4 == 0x63c) { -      return 0x0f & resp.getSW(); -    } -     -    switch (resp.getSW()) { -    case 0x6983: +    } else if (resp.getSW() == 0x6983) {        // authentication method blocked        throw new LockedException(); -   -    default: +    } else if (resp.getSW() == 0x6984) { +      throw new NotActivatedException(); +    } else if (resp.getSW() >> 4 == 0x63c) { +      return 0x0f & resp.getSW(); +    } else {        String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW());         log.info(msg);        throw new SignatureCardException(msg);      } -    -        }    protected int activatePIN(CardChannel channel, PINSpec pinSpec, -      PINProvider provider) throws SignatureCardException, +      ModifyPINGUI provider) throws SignatureCardException,        InterruptedException, CardException { -    NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( +    ResponseAPDU resp; +    if (version < 1.2) { +      NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( +          new byte[] { +              (byte) 0x00, (byte) 0x24, (byte) 0x01, pinSpec.getKID(), (byte) 0x08, +              (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +              (byte) 0xff, (byte) 0xff, (byte) 0xff }, +          1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); + +      resp = reader.modify(channel, apduSpec, provider, pinSpec); +    } else { +      NewReferenceDataAPDUSpec apduSpec = new NewReferenceDataAPDUSpec( +          new byte[] { +              (byte) 0x00, (byte) 0x24, (byte) 0x00, pinSpec.getKID(), (byte) 0x10, +              (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, +              (byte) 0xff, (byte) 0xff, (byte) 0xff,  +              (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +              (byte) 0xff, (byte) 0xff, (byte) 0xff }, +          1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); +      apduSpec.setPinInsertionOffsetNew(8); +      resp = reader.modify(channel, apduSpec, provider, pinSpec); +    } + +    if (resp.getSW() == 0x9000) { +      return -1; +    } else { +      String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW()); +      log.info(msg); +      throw new SignatureCardException(msg); +    } +  } +   +  protected int unblockPIN(CardChannel channel, PINSpec pinSpec, +      ModifyPINGUI provider, int retries) throws SignatureCardException, +      InterruptedException, CardException { + +    if (version < 1.2) { +      // would return 0x6982 (Security status not satisfied) +      throw new SignatureCardException("RESET RETRY COUNTER is not supported by this card."); +    } + +    ResetRetryCounterAPDUSpec apduSpec = new ResetRetryCounterAPDUSpec(          new byte[] { -            (byte) 0x00, (byte) 0x24, (byte) 0x01, pinSpec.getKID(), (byte) 0x08, +            (byte) 0x00, (byte) 0x2c, (byte) 0x00, pinSpec.getKID(), (byte) 0x10,              (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, -            (byte) 0xff, (byte) 0xff, (byte) 0xff },  -        1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); -     -    ResponseAPDU resp = reader.activate(channel, apduSpec, pinSpec, provider); -     -    switch (resp.getSW()) { -     -    case 0x9000: -      return -1; +            (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0xff, (byte) 0xff, (byte) 0xff }, +        1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4, 8); -    case 0x6983: -      // authentication method blocked -      throw new LockedException(); +    ResponseAPDU resp = reader.modify(channel, apduSpec, provider, pinSpec, retries); -    default: -      String msg = "CHANGE REFERENCE DATA failed. SW=" + Integer.toHexString(resp.getSW());  +    if (resp.getSW() == 0x9000) { +      return -1; +    } else if (resp.getSW() == 0x6983) { +      // PUK blocked +      throw new LockedException(); +    } else if (resp.getSW() == 0x6984) { +      throw new NotActivatedException(); +    } else if (resp.getSW() >> 4 == 0x63c) { +      return 0x0f & resp.getSW(); +    } else { +      String msg = "RESET RETRY COUNTER failed. SW=" + Integer.toHexString(resp.getSW());        log.info(msg);        throw new SignatureCardException(msg);      } -        } -   +    protected void execSELECT_MF(CardChannel channel) throws CardException, SignatureCardException {      ResponseAPDU resp = channel.transmit(          new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index 670704d5..73c7faa8 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -40,15 +40,12 @@ import java.util.Enumeration;  import java.util.Locale;  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.ccid.CCID; +import at.gv.egiz.smcc.pin.gui.PINGUI;  /**   * @@ -280,7 +277,7 @@ public class SWCard implements SignatureCard {    } -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) throws SignatureCardException { +  public byte[] getInfobox(String infobox, PINGUI provider, String domainId) throws SignatureCardException {      String fileName = getFileName(infobox + ".ibx");      FileInputStream file; @@ -309,7 +306,7 @@ public class SWCard implements SignatureCard {    }    @Override -  public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +  public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINGUI provider, String alg) throws SignatureCardException, InterruptedException, IOException {      // KeyStore password      char[] password = getPassword(keyboxName); @@ -396,101 +393,4 @@ public class SWCard implements SignatureCard {    @Override    public void reset() throws SignatureCardException {    } - -  @Override -  public CCID getReader() { -    return new CCID() { - -      @Override -      public boolean hasFeature(Byte feature) { -        return false; -      } - -      @Override -      public byte getbTimeOut() { -        return 0; -      } - -      @Override -      public byte getbTimeOut2() { -        return 0; -      } - -      @Override -      public byte getwPINMaxExtraDigitL() { -        return 0x12; -      } - -      @Override -      public byte getwPINMaxExtraDigitH() { -        return 0x00; -      } - -      @Override -      public byte getbEntryValidationCondition() { -        return 0x02; -      } - -      @Override -      public Card connect() { -        return null; -      } - -      @Override -      public String getName() { -        return "Software CardReader"; -      } - -      @Override -      public byte[] verifyPin(byte[] PIN_VERIFY) throws CardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public byte[] verifyPinDirect(byte[] PIN_VERIFY) throws CardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public byte[] modifyPin(byte[] PIN_MODIFY) throws CardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public byte[] modifyPinDirect(byte[] PIN_MODIFY) throws CardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public void setDisablePinpad(boolean disable) { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, -          PINSpec pinSpec, PINProvider provider, int retries) -          throws CancelledException, InterruptedException, CardException, -          SignatureCardException { -        throw new UnsupportedOperationException("Not supported yet."); -      } - -      @Override -      public ResponseAPDU activate(CardChannel channel, -          NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec, -          PINProvider provider) throws CancelledException, -          InterruptedException, CardException, SignatureCardException { -        // TODO Auto-generated method stub -        return null; -      } - -      @Override -      public ResponseAPDU modify(CardChannel channel, -          ChangeReferenceDataAPDUSpec apduSpec, PINSpec pinSpec, -          ChangePINProvider provider, int retries) throws CancelledException, -          InterruptedException, CardException, SignatureCardException { -        // TODO Auto-generated method stub -        return null; -      } -    }; -  }  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index 3d56f97b..fa589b84 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -17,8 +17,7 @@  package at.gv.egiz.smcc; -import at.gv.egiz.smcc.ccid.CCID; - +import at.gv.egiz.smcc.pin.gui.PINGUI;  import java.io.IOException;  import java.io.InputStream;  import java.util.Locale; @@ -99,7 +98,7 @@ public interface SignatureCard {     * @throws SignatureCardException     * @throws InterruptedException if applet is destroyed while in pin dialog     */ -  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +  public byte[] getInfobox(String infobox, PINGUI pinGUI, String domainId)        throws SignatureCardException, InterruptedException;    /** @@ -114,9 +113,7 @@ public interface SignatureCard {     * @throws IOException      */    public byte[] createSignature(InputStream input, KeyboxName keyboxName, -      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException; - -  public CCID getReader(); +      PINGUI pinGUI, String alg) throws SignatureCardException, InterruptedException, IOException;    /**     * Sets the local for evtl. required callbacks (e.g. PINSpec) diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java new file mode 100644 index 00000000..00dc2d0e --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINGUI.java @@ -0,0 +1,36 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + + +public interface ModifyPINGUI extends ModifyPINProvider { + +  void modifyPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException; +  void finishDirect(); + +  void enterCurrentPIN(PINSpec spec, int retries); +  void enterNewPIN(PINSpec spec); +  void confirmNewPIN(PINSpec spec); +  void validKeyPressed(); +  void correctionButtonPressed(); +  void allKeysCleared(); +  /** called prior to MODIFY_PIN_FINISH control command transmission (clear display or display wait message) */ +  void finish(); +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java index 41010551..36f0097d 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ChangePINProvider.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/ModifyPINProvider.java @@ -14,13 +14,22 @@  * See the License for the specific language governing permissions and  * limitations under the License.  */ -package at.gv.egiz.smcc; +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +  /** - * + * user interface for "software pin-entry" of + * <ul> + * <li> current pin and new pin (change pin) + * <li> new pin (pin activation, no current pin) + * <li> puk and new pin (probably verify only?) + * </ul>   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */ -public interface ChangePINProvider extends PINProvider { +public interface ModifyPINProvider {    /**     * @@ -30,7 +39,10 @@ public interface ChangePINProvider extends PINProvider {     * @throws at.gv.egiz.smcc.CancelledException if cancelled by user     * @throws java.lang.InterruptedException     */ -  public char[] provideOldPIN(PINSpec spec, int retries) +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException; + +  public char[] provideNewPIN(PINSpec spec)            throws CancelledException, InterruptedException;  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java new file mode 100644 index 00000000..5199977b --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINGUI.java @@ -0,0 +1,42 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + + +/** + * Display messages for pinpad pin-entry. + * Provides an interface for two types of pinpad pin-entry: pinpad-direct and pinpad-start/finish + * @author clemens.orthacker@iaik.tugraz.at + */ +public interface PINGUI extends PINProvider { + +  void enterPINDirect(PINSpec spec, int retries) +          throws CancelledException, InterruptedException; +   +  /** +   * @throws CancelledException, InterruptedException if signature-data dialog is interrupted or cancelled +   */ +  void enterPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException; +  void validKeyPressed(); +  void correctionButtonPressed(); +  void allKeysCleared(); +   +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java index 5c294b5b..3bf49888 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINProvider.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java @@ -14,7 +14,11 @@  * See the License for the specific language governing permissions and  * limitations under the License.  */ -package at.gv.egiz.smcc; +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; +  /**   * The number of retries is not fixed and there is no way (?) to obtain this value. @@ -39,7 +43,7 @@ public interface PINProvider {     * @throws at.gv.egiz.smcc.CancelledException     * @throws java.lang.InterruptedException     */ -  public char[] providePIN(PINSpec spec, int retries) +  char[] providePIN(PINSpec pinSpec, int retries)            throws CancelledException, InterruptedException;  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java new file mode 100644 index 00000000..a1246dd6 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/CardReader.java @@ -0,0 +1,92 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.reader; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.ResponseAPDU; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import javax.smartcardio.Card; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public interface CardReader { + + +  String[] FEATURES = new String[]{"NO_FEATURE", +    "FEATURE_VERIFY_PIN_START", +    "FEATURE_VERIFY_PIN_FINISH", +    "FEATURE_MODIFY_PIN_START", +    "FEATURE_MODIFY_PIN_FINISH", +    "FEATURE_GET_KEY_PRESSED", +    "FEATURE_VERIFY_PIN_DIRECT", +    "FEATURE_MODIFY_PIN_DIRECT", +    "FEATURE_MCT_READER_DIRECT", +    "FEATURE_MCT_UNIVERSAL", +    "FEATURE_IFD_PIN_PROPERTIES", +    "FEATURE_ABORT", +    "FEATURE_SET_SPE_MESSAGE", +    "FEATURE_VERIFY_PIN_DIRECT_APP_ID", +    "FEATURE_MODIFY_PIN_DIRECT_APP_ID", +    "FEATURE_WRITE_DISPLAY", +    "FEATURE_GET_KEY", +    "FEATURE_IFD_DISPLAY_PROPERTIES"}; + +  Byte FEATURE_VERIFY_PIN_START = new Byte((byte) 0x01); +  Byte FEATURE_VERIFY_PIN_FINISH = new Byte((byte) 0x02); +  Byte FEATURE_MODIFY_PIN_START = new Byte((byte) 0x03); +  Byte FEATURE_MODIFY_PIN_FINISH = new Byte((byte) 0x04); +  Byte FEATURE_GET_KEY_PRESSED = new Byte((byte) 0x05); +  Byte FEATURE_VERIFY_PIN_DIRECT = new Byte((byte) 0x06); +  Byte FEATURE_MODIFY_PIN_DIRECT = new Byte((byte) 0x07); +  Byte FEATURE_MCT_READER_DIRECT = new Byte((byte) 0x08); +  Byte FEATURE_MCT_UNIVERSAL = new Byte((byte) 0x09); +  Byte FEATURE_IFD_PIN_PROPERTIES = new Byte((byte) 0x0a); +  //TODO continue list + + +  Card connect() throws CardException; + +  boolean hasFeature(Byte feature); + +  ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, +          PINGUI pinGUI, PINSpec pinSpec, int retries) +      throws CancelledException, InterruptedException, CardException, SignatureCardException; + +  ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +      throws CancelledException, InterruptedException, CardException, SignatureCardException; + +  ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec) +      throws CancelledException, InterruptedException, CardException, SignatureCardException; + +  ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +      throws CancelledException, InterruptedException, CardException, SignatureCardException; +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java new file mode 100644 index 00000000..45ea7a5a --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/DefaultCardReader.java @@ -0,0 +1,106 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.reader; + + +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.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.util.ISO7816Utils; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class DefaultCardReader implements CardReader { + +  protected final static Log log = LogFactory.getLog(DefaultCardReader.class); + +  protected CardTerminal ct; +  protected String name; + +  public DefaultCardReader(CardTerminal ct) { +    if (ct == null) { +      throw new NullPointerException("no card or card terminal provided"); +    } +    this.ct = ct; +    this.name = ct.getName(); +  } + +  @Override +  public ResponseAPDU verify(CardChannel channel, VerifyAPDUSpec apduSpec, +          PINGUI pinGUI, PINSpec pinSpec, int retries) +        throws SignatureCardException, CardException, InterruptedException { + +    log.debug("VERIFY"); +    return channel.transmit(ISO7816Utils.createVerifyAPDU(apduSpec, pinGUI.providePIN(pinSpec, retries))); +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +        throws SignatureCardException, CardException, InterruptedException { +    log.debug("MODIFY (CHANGE_REFERENCE_DATA)"); +    char[] oldPin = pinGUI.provideCurrentPIN(pinSpec, retries); +    char[] newPin = pinGUI.provideNewPIN(pinSpec); +    return channel.transmit(ISO7816Utils.createChangeReferenceDataAPDU(apduSpec, oldPin, newPin)); +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec) +        throws SignatureCardException, CardException, InterruptedException { +    log.debug("MODIFY (NEW_REFERENCE_DATA)"); +    char[] newPIN = pinGUI.provideNewPIN(pinSpec); +    return channel.transmit(ISO7816Utils.createNewReferenceDataAPDU(apduSpec, newPIN)); +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +          throws InterruptedException, CardException, SignatureCardException { +    log.debug("MODIFY (RESET_RETRY_COUNTER)"); +    //TODO +    return modify(channel, (ChangeReferenceDataAPDUSpec) apduSpec, pinGUI, pinSpec, retries); +  } + +  @Override +  public Card connect() throws CardException { +    log.debug("connect icc"); +    return ct.connect("*"); +  } + +  @Override +  public boolean hasFeature(Byte feature) { +    return false; +  } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java new file mode 100644 index 00000000..c2537af8 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java @@ -0,0 +1,703 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.reader; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +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.ChangeReferenceDataAPDUSpec; +import at.gv.egiz.smcc.NewReferenceDataAPDUSpec; +import at.gv.egiz.smcc.PINConfirmationException; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINOperationAbortedException; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.ResetRetryCounterAPDUSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.TimeoutException; +import at.gv.egiz.smcc.VerifyAPDUSpec; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.util.SMCCHelper; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PinpadCardReader extends DefaultCardReader { + +  public static final int PIN_ENTRY_POLLING_INTERVAL = 10; + +  protected final static Log log = LogFactory.getLog(PinpadCardReader.class); + +  protected byte bEntryValidationCondition = 0x02;  // validation key pressed +  protected byte bTimeOut = 0x3c;                   // 60sec (= max on ReinerSCT) +  protected byte bTimeOut2 = 0x00;                  // default (attention with SCM) +  protected byte wPINMaxExtraDigitH = 0x00;         // min pin length zero digits +  protected byte wPINMaxExtraDigitL = 0x0c;         // max pin length 12 digits + +  /** +   * supported features and respective control codes +   */ +  protected Map<Byte, Integer> features; +  protected boolean VERIFY, MODIFY, VERIFY_DIRECT, MODIFY_DIRECT; + +  public PinpadCardReader(CardTerminal ct, Map<Byte, Integer> features) { +    super(ct); +    if (features == null) { +      throw new NullPointerException("Pinpad card reader does not support any features"); +    } +    this.features = features; + +    if (features.containsKey(FEATURE_VERIFY_PIN_START) && +        features.containsKey(FEATURE_GET_KEY_PRESSED) && +        features.containsKey(FEATURE_VERIFY_PIN_FINISH)) { +      VERIFY = true; +    } +    if (features.containsKey(FEATURE_MODIFY_PIN_START) && +        features.containsKey(FEATURE_GET_KEY_PRESSED) && +        features.containsKey(FEATURE_MODIFY_PIN_FINISH)) { +      MODIFY = true; +    } +    if (features.containsKey(FEATURE_VERIFY_PIN_DIRECT)) { +      VERIFY_DIRECT = true; +    } +    if (features.containsKey(FEATURE_MODIFY_PIN_DIRECT)) { +      MODIFY_DIRECT = true; +    } + +    if (name != null) { +      name = name.toLowerCase(); +      //ReinerSCT: http://support.reiner-sct.de/downloads/LINUX +      //           http://www.linux-club.de/viewtopic.php?f=61&t=101287&start=0 +      //old: REINER SCT CyberJack 00 00 +      //new (CCID): 0C4B/0300 Reiner-SCT cyberJack pinpad(a) 00 00 +      //Snow Leopard: Reiner-SCT cyberJack pinpad(a) 00 00 +      //display: REINER SCT CyberJack 00 00 +      if(name.startsWith("gemplus gempc pinpad") || name.startsWith("gemalto gempc pinpad")) { +        log.debug("setting custom wPINMaxExtraDigitH (0x04) for " + name); +        wPINMaxExtraDigitH = 0x04; +        log.debug("setting custom wPINMaxExtraDigitL (0x08) for " + name); +        wPINMaxExtraDigitL = 0x08; +      } else if (name.startsWith("omnikey cardman 3621")) { +        log.debug("setting custom wPINMaxExtraDigitH (0x01) for " + name); +        wPINMaxExtraDigitH = 0x01; +      } else if (name.startsWith("scm spr 532") || name.startsWith("scm microsystems inc. sprx32 usb smart card reader")) { +        log.debug("setting custom bTimeOut (0x3c) for " + name); +        bTimeOut = 0x3c; +        log.debug("setting custom bTimeOut2 (0x0f) for " + name); +        bTimeOut2 = 0x0f; +      } else if (name.startsWith("cherry smartboard xx44")) { +        log.debug("setting custom wPINMaxExtraDigitH (0x01) for " + name); +        wPINMaxExtraDigitH = 0x01; +      } +    } + +  } + +  @Override +  public boolean hasFeature(Byte feature) { +    return features.containsKey(feature); +  } +   +  private void VERIFY_PIN_START(Card icc, byte[] PIN_VERIFY) throws CardException { +    int ioctl = features.get(FEATURE_VERIFY_PIN_START); +    if (log.isTraceEnabled()) { +      log.trace("VERIFY_PIN_START (" + Integer.toHexString(ioctl) + +              ")  " + SMCCHelper.toString(PIN_VERIFY)); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, PIN_VERIFY); +    if (resp != null && resp.length > 0) { +      if (resp[0] == (byte) 0x57) { +        log.error("Invalid parameter in PIN_VERIFY structure"); +        throw new CardException("ERROR_INVALID_PARAMETER"); +      } else { +        log.error("unexpected response to VERIFY_PIN_START: " + +                SMCCHelper.toString(resp)); +        throw new CardException("unexpected response to VERIFY_PIN_START: " + +                SMCCHelper.toString(resp)); +      } +    } +  } + +  private byte GET_KEY_PRESSED(Card icc) throws CardException { +    int ioctl = features.get(FEATURE_GET_KEY_PRESSED); +    byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); +    if (resp != null && resp.length == 1) { +//      if (log.isTraceEnabled()) { +//        log.trace("response " + SMCCHelper.toString(resp)); +//      } +      return resp[0]; +    } +    log.error("unexpected response to GET_KEY_PRESSED: " + +            SMCCHelper.toString(resp)); +    throw new CardException("unexpected response to GET_KEY_PRESSED: " + +            SMCCHelper.toString(resp)); +  } + +  private byte[] VERIFY_PIN_FINISH(Card icc) throws CardException { +    int ioctl = features.get(FEATURE_VERIFY_PIN_FINISH); +    if (log.isTraceEnabled()) { +      log.trace("VERIFY_PIN_FINISH (" + Integer.toHexString(ioctl) + ")"); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); +    if (resp != null && resp.length == 2) { +      if (log.isTraceEnabled()) { +        log.trace("response " + SMCCHelper.toString(resp)); +      } +      return resp; +    } +    log.error("unexpected response to VERIFY_PIN_FINISH: " + +            SMCCHelper.toString(resp)); +    throw new CardException("unexpected response to VERIFY_PIN_FINISH: " + +            SMCCHelper.toString(resp)); +  } + +  private void MODIFY_PIN_START(Card icc, byte[] PIN_MODIFY) throws CardException { +    int ioctl = features.get(FEATURE_MODIFY_PIN_START); +    if (log.isTraceEnabled()) { +      log.trace("MODFIY_PIN_START (" + Integer.toHexString(ioctl) + +              ")  " + SMCCHelper.toString(PIN_MODIFY)); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, PIN_MODIFY); +    if (resp != null && resp.length > 0) { +      if (resp[0] == (byte) 0x57) { +        log.error("Invalid parameter in PIN_MODIFY structure"); +        throw new CardException("ERROR_INVALID_PARAMETER"); +      } else { +        log.error("unexpected response to MODIFY_PIN_START: " + +                SMCCHelper.toString(resp)); +        throw new CardException("unexpected response to MODIFY_PIN_START: " + +                SMCCHelper.toString(resp)); +      } +    } +  } + +  private byte[] MODIFY_PIN_FINISH(Card icc) throws CardException { +    int ioctl = features.get(FEATURE_MODIFY_PIN_FINISH); +    if (log.isTraceEnabled()) { +      log.trace("MODIFY_PIN_FINISH (" + Integer.toHexString(ioctl) + ")"); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, new byte[0]); +    if (resp != null && resp.length == 2) { +      if (log.isTraceEnabled()) { +        log.trace("response " + SMCCHelper.toString(resp)); +      } +      return resp; +    } +    log.error("unexpected response to MODIFY_PIN_FINISH: " + +            SMCCHelper.toString(resp)); +    throw new CardException("unexpected response to MODIFY_PIN_FINISH: " + +            SMCCHelper.toString(resp)); +  } + +  private byte[] VERIFY_PIN_DIRECT(Card icc, byte[] PIN_VERIFY) throws CardException { +    int ioctl = features.get(FEATURE_VERIFY_PIN_DIRECT); +    if (log.isTraceEnabled()) { +      log.trace("VERIFY_PIN_DIRECT (" + Integer.toHexString(ioctl) + +              ")  " + SMCCHelper.toString(PIN_VERIFY)); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, PIN_VERIFY); +    if (log.isTraceEnabled()) { +      log.trace("response " + SMCCHelper.toString(resp)); +    } +    return resp; +  } + +  private byte[] verifyPin(Card icc, byte[] PIN_VERIFY, PINGUI pinGUI)  +          throws SignatureCardException, CardException, InterruptedException { + +//    pinGUI.enterPIN(pinSpec, retries); + +    log.debug("VERIFY_PIN_START [" + FEATURES[FEATURE_VERIFY_PIN_START] + "]"); +    VERIFY_PIN_START(icc, PIN_VERIFY); + +    byte resp; +    do { +      resp = GET_KEY_PRESSED(icc); +      if (resp == (byte) 0x00) { +        synchronized(this) { +          try { +            wait(PIN_ENTRY_POLLING_INTERVAL); +          } catch (InterruptedException ex) { +            log.error("interrupted in VERIFY_PIN"); +          } +        } +      } else if (resp == (byte) 0x0d) { +        log.debug("GET_KEY_PRESSED: 0x0d (user confirmed)"); +        break; +      } else if (resp == (byte) 0x2b) { +        log.trace("GET_KEY_PRESSED: 0x2b (user entered valid key 0-9)"); +        pinGUI.validKeyPressed(); +      } else if (resp == (byte) 0x1b) { +        log.debug("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)"); +        break; // returns 0x6401 +      } else if (resp == (byte) 0x08) { +        log.debug("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)"); +        pinGUI.correctionButtonPressed(); +      } else if (resp == (byte) 0x0e) { +        log.debug("GET_KEY_PRESSED: 0x0e (timeout occured)"); +        break; // return 0x6400 +      } else if (resp == (byte) 0x40) { +        log.debug("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)"); +        throw new PINOperationAbortedException("PIN_Operation_Aborted (0x40)"); +      } else if (resp == (byte) 0x0a) { +        log.debug("GET_KEY_PRESSED: 0x0a (all keys cleared"); +        pinGUI.allKeysCleared(); +      } else { +        log.error("unexpected response to GET_KEY_PRESSED: " + +            Integer.toHexString(resp)); +        throw new CardException("unexpected response to GET_KEY_PRESSED: " + +            Integer.toHexString(resp)); +      } +    } while (true);  + +    return VERIFY_PIN_FINISH(icc); +  } + +  /** +   * does not display the first pin dialog (enterCurrentPIN or enterNewPIN, depends on bConfirmPIN), +   * since this is easier to do in calling modify() +   */ +  private byte[] modifyPin(Card icc, byte[] PIN_MODIFY, ModifyPINGUI pinGUI, PINSpec pINSpec) +          throws PINOperationAbortedException, CardException { + +    byte pinConfirmations = (byte) 0x00; //b0: new pin not entered (0) / entered (1) +                                         //b1: current pin not entered (0) / entered (1) +    byte bConfirmPIN = PIN_MODIFY[9]; +     +//    if ((bConfirmPIN & (byte) 0x02) == 0) { +//      log.debug("no current PIN entry requested"); +//      pinGUI.enterNewPIN(pINSpec); +//    } else { +//      log.debug("current PIN entry requested"); +//      pinGUI.enterCurrentPIN(pINSpec, retries); +//    } + +    log.debug("MODIFY_PIN_START [" + FEATURES[FEATURE_MODIFY_PIN_START] + "]"); +    MODIFY_PIN_START(icc, PIN_MODIFY); + +    byte resp; +    while (true) { +      resp = GET_KEY_PRESSED(icc); +      if (resp == (byte) 0x00) { +        synchronized(this) { +          try { +            wait(PIN_ENTRY_POLLING_INTERVAL); +          } catch (InterruptedException ex) { +            log.error("interrupted in MODIFY_PIN"); +          } +        } +      } else if (resp == (byte) 0x0d) { +        if (log.isTraceEnabled()) { +          log.trace("requested pin confirmations: 0b" + Integer.toBinaryString(bConfirmPIN & 0xff)); +          log.trace("performed pin confirmations: 0b" + Integer.toBinaryString(pinConfirmations & 0xff)); +        } +        log.debug("GET_KEY_PRESSED: 0x0d (user confirmed)"); +        if (pinConfirmations == bConfirmPIN) { +          break; +        } else if ((bConfirmPIN & (byte) 0x02) == 0 || +            (pinConfirmations & (byte) 0x02) == (byte) 0x02) { +          // no current pin entry or current pin entry already performed +          if ((pinConfirmations & (byte) 0x01) == 0) { +            // new pin +            pinConfirmations |= (byte) 0x01; +            pinGUI.confirmNewPIN(pINSpec); +          } // else: new pin confirmed +        } else { +          // current pin entry +          pinConfirmations |= (byte) 0x02; +          pinGUI.enterNewPIN(pINSpec); +        } +      } else if (resp == (byte) 0x2b) { +        log.trace("GET_KEY_PRESSED: 0x2b (user entered valid key 0-9)"); +        pinGUI.validKeyPressed(); +      } else if (resp == (byte) 0x1b) { +        log.debug("GET_KEY_PRESSED: 0x1b (user cancelled VERIFY_PIN via cancel button)"); +        break; // returns 0x6401 +      } else if (resp == (byte) 0x08) { +        log.debug("GET_KEY_PRESSED: 0x08 (user pressed correction/backspace button)"); +        pinGUI.correctionButtonPressed(); +      } else if (resp == (byte) 0x0e) { +        log.debug("GET_KEY_PRESSED: 0x0e (timeout occured)"); +        break; // return 0x6400 +      } else if (resp == (byte) 0x40) { +        log.debug("GET_KEY_PRESSED: 0x40 (PIN_Operation_Aborted)"); +        throw new PINOperationAbortedException("PIN_Operation_Aborted (0x40)"); +      } else if (resp == (byte) 0x0a) { +        log.debug("GET_KEY_PRESSED: 0x0a (all keys cleared"); +        pinGUI.allKeysCleared(); +      } else { +        log.error("unexpected response to GET_KEY_PRESSED: " + +            Integer.toHexString(resp)); +        throw new CardException("unexpected response to GET_KEY_PRESSED: " + +            Integer.toHexString(resp)); +      } + +    } + +    pinGUI.finish(); +    return MODIFY_PIN_FINISH(icc); +  } + +  private byte[] MODIFY_PIN_DIRECT(Card icc, byte[] PIN_MODIFY) throws CardException { +    int ioctl = features.get(FEATURE_MODIFY_PIN_DIRECT); +    if (log.isTraceEnabled()) { +      log.trace("MODIFY_PIN_DIRECT (" + Integer.toHexString(ioctl) + +              ")  " + SMCCHelper.toString(PIN_MODIFY)); +    } +    byte[] resp = icc.transmitControlCommand(ioctl, PIN_MODIFY); +    if (log.isTraceEnabled()) { +      log.trace("response " + SMCCHelper.toString(resp)); +    } +    return resp; +  } +   +  protected byte[] createPINModifyStructure(NewReferenceDataAPDUSpec apduSpec, PINSpec pinSpec) { + +    ByteArrayOutputStream s = new ByteArrayOutputStream(); +    // bTimeOut +    s.write(bTimeOut); +    // bTimeOut2 +    s.write(bTimeOut2); +    // 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(), wPINMaxExtraDigitL)); +    s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); +    // bConfirmPIN +    s.write(0x01); +    // bEntryValidationCondition +    s.write(bEntryValidationCondition); +    // bNumberMessage +    s.write(0x02); +    // wLangId English (United States), see http://www.usb.org/developers/docs/USB_LANGIDs.pdf +    s.write(0x09); +    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) { +    //TODO bInsertionOffsetOld (0x00), bConfirmPIN (0x01), bNumberMessage (0x02), bMsgIndex1/2/3 + +    ByteArrayOutputStream s = new ByteArrayOutputStream(); +    // bTimeOut +    s.write(bTimeOut); +    // bTimeOut2 +    s.write(bTimeOut2); +    // 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 (0x00 for no old pin?) +    s.write(apduSpec.getPinInsertionOffsetOld()); +    // bInsertionOffsetNew +    s.write(apduSpec.getPinInsertionOffsetNew()); +    // wPINMaxExtraDigit +    s.write(Math.min(pinSpec.getMaxLength(), wPINMaxExtraDigitL)); +    s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); +    // bConfirmPIN +    s.write(0x03); +    // bEntryValidationCondition +    s.write(bEntryValidationCondition); +    // bNumberMessage +    s.write(0x03); +    // wLangId English (United States), see http://www.usb.org/developers/docs/USB_LANGIDs.pdf +    s.write(0x09); +    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(bTimeOut); +    // bTimeOut2 +    s.write(bTimeOut2); +    // 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(), wPINMaxExtraDigitL)); // max PIN length +    s.write(Math.max(pinSpec.getMinLength(), wPINMaxExtraDigitH)); // min PIN length +    // bEntryValidationCondition +    s.write(bEntryValidationCondition); +    // bNumberMessage +    s.write(0x01); +    // wLangId +    s.write(0x09); +    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, +          PINGUI pinGUI, PINSpec pinSpec, int retries) +        throws SignatureCardException, CardException, InterruptedException { + +    ResponseAPDU resp = null; + +    byte[] s = createPINVerifyStructure(apduSpec, pinSpec); +    Card icc = channel.getCard(); + +    if (VERIFY) { +      pinGUI.enterPIN(pinSpec, retries); +      resp = new ResponseAPDU(verifyPin(icc, s, pinGUI)); +    } else if (VERIFY_DIRECT) { +      pinGUI.enterPINDirect(pinSpec, retries); +      log.debug("VERIFY_PIN_DIRECT [" + FEATURES[FEATURE_VERIFY_PIN_DIRECT] + "]"); +      resp = new ResponseAPDU(VERIFY_PIN_DIRECT(icc, s)); +    } else { +      log.warn("falling back to default pin-entry"); +      return super.verify(channel, apduSpec, pinGUI, pinSpec, retries); +    } + +    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 0x6403: +          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; +    } +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, ChangeReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +        throws SignatureCardException, CardException, InterruptedException { +     +    ResponseAPDU resp = null; + +    byte[] s = createPINModifyStructure(apduSpec, pinSpec); +    Card icc = channel.getCard(); +     +    if (MODIFY) { +      pinGUI.enterCurrentPIN(pinSpec, retries); +      resp = new ResponseAPDU(modifyPin(icc, s, pinGUI, pinSpec)); +    } else if (MODIFY_DIRECT) { +      pinGUI.modifyPINDirect(pinSpec, retries); +      log.debug("MODIFY_PIN_DIRECT [" + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "]"); +      resp = new ResponseAPDU(MODIFY_PIN_DIRECT(icc, s)); +    } else { +      log.warn("falling back to default pin-entry"); +      return super.modify(channel, apduSpec, pinGUI, pinSpec, retries); +    } + +    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 0x6402: +        log.debug("Modify PIN operation failed because two 'new PIN' " + +                "entries do not match"); +        throw new PINConfirmationException(); +      case 0x6403: +        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; +    } +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, NewReferenceDataAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec) +        throws SignatureCardException, CardException, InterruptedException { + +    ResponseAPDU resp = null; + +    byte[] s = createPINModifyStructure(apduSpec, pinSpec); +    Card icc = channel.getCard(); + +    if (MODIFY) { +      pinGUI.enterNewPIN(pinSpec); +      resp = new ResponseAPDU(modifyPin(icc, s, pinGUI, pinSpec)); +    } else if (MODIFY_DIRECT) { +      pinGUI.modifyPINDirect(pinSpec, -1); +      log.debug("MODIFY_PIN_DIRECT [" + FEATURES[FEATURE_MODIFY_PIN_DIRECT] + "]"); +      resp = new ResponseAPDU(MODIFY_PIN_DIRECT(icc, s)); +    } else { +      log.warn("falling back to default pin-entry"); +      return super.modify(channel, apduSpec, pinGUI, pinSpec); +    } + +    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 0x6402: +        log.debug("Modify PIN operation failed because two 'new PIN' " + +                "entries do not match"); +        throw new PINConfirmationException(); +      case 0x6403: +        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; +    } +  } + +  @Override +  public ResponseAPDU modify(CardChannel channel, ResetRetryCounterAPDUSpec apduSpec, +          ModifyPINGUI pinGUI, PINSpec pinSpec, int retries) +          throws InterruptedException, CardException, SignatureCardException { +    //TODO +    return modify(channel, (ChangeReferenceDataAPDUSpec) apduSpec, pinGUI, pinSpec, retries); +  } +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java new file mode 100644 index 00000000..eb197d9f --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/ReaderFactory.java @@ -0,0 +1,128 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package at.gv.egiz.smcc.reader; + +import at.gv.egiz.smcc.conf.SMCCConfiguration; +import at.gv.egiz.smcc.util.SMCCHelper; +import java.util.HashMap; +import java.util.Map; +import javax.smartcardio.Card; +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class ReaderFactory { + +  protected final static Log log = LogFactory.getLog(ReaderFactory.class); +   +  protected SMCCConfiguration configuration; + +  private ReaderFactory() { +  } + +  /** +   * @param configuration the configuration to set +   */ +  public void setConfiguration(SMCCConfiguration configuration) { +    this.configuration = configuration; +  } + +  public static CardReader getReader(Card icc, CardTerminal ct) { + +    String name = ct.getName(); +    log.info("creating reader " + name); + +    Map<Byte, Integer> features = queryFeatures(icc); +    boolean disablePinpad = false; +    CardReader reader; + +        //TODO query application context for reader config +//    if (configuration != null) { +//      String disablePinpad = configuration.getProperty(SMCCConfiguration.DISABLE_PINPAD_P); +//      log.debug("setting disablePinpad to " + Boolean.parseBoolean(disablePinpad)); +//      reader.setDisablePinpad(Boolean.parseBoolean(disablePinpad)); +//    } +    log.warn("card reader configuration is not considered"); + +    if (features.isEmpty() || disablePinpad) { +      reader = new DefaultCardReader(ct); +    } else { +      reader = new PinpadCardReader(ct, features); +    } + +    return reader; +  } + +  private static int CTL_CODE(int code) { +    String os_name = System.getProperty("os.name").toLowerCase(); +    if (os_name.indexOf("windows") > -1) { +      // cf. WinIOCTL.h +      return (0x31 << 16 | (code) << 2); +    } +    // cf. reader.h +    return 0x42000000 + (code); +  } + +  static int IOCTL_GET_FEATURE_REQUEST = CTL_CODE(3400); + +  private static Map<Byte, Integer> queryFeatures(Card icc) { +    Map<Byte, Integer> features = new HashMap<Byte, Integer>(); + +    if (icc == null) { +      log.warn("invalid card handle, cannot query ifd features"); +    } else { +      try { +        if (log.isTraceEnabled()) { +          log.trace("GET_FEATURE_REQUEST " + Integer.toHexString(IOCTL_GET_FEATURE_REQUEST)); +        } +        byte[] resp = icc.transmitControlCommand(IOCTL_GET_FEATURE_REQUEST, +                new byte[0]); + +        if (log.isTraceEnabled()) { +          log.trace("Response TLV " + SMCCHelper.toString(resp)); +        } +        // tag +        // length in bytes (always 4) +        // control code value for supported feature (in big endian) +        for (int i = 0; i < resp.length; i += 6) { +          Byte feature = new Byte(resp[i]); +          Integer ioctl = new Integer((0xff & resp[i + 2]) << 24) | +                  ((0xff & resp[i + 3]) << 16) | +                  ((0xff & resp[i + 4]) << 8) | +                  (0xff & resp[i + 5]); +          if (log.isInfoEnabled()) { +            log.info("IFD supports " + CardReader.FEATURES[feature.intValue()] + +                    ": " + Integer.toHexString(ioctl.intValue())); +          } +          features.put(feature, ioctl); +        } +      } catch (CardException ex) { +        log.debug("Failed to query IFD features: " + ex.getMessage()); +        log.trace(ex); +        log.info("IFD does not support secure pin entry"); +      } +    } +    return features; +  } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java b/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java index 137de509..affb06ff 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/AbstractAppl.java @@ -51,6 +51,7 @@ public abstract class AbstractAppl implements CardAppl {      return files;    } +  @Override    public abstract void setPin(int kid, char[] value);  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java index 6017bcce..3dfc8510 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardEmul.java @@ -28,15 +28,15 @@ import javax.smartcardio.CardException;  @SuppressWarnings("restriction")  public abstract class CardEmul extends Card { -  protected Thread exclThread = null; -  protected CardChannel channel = newCardChannel(this); +  protected Thread exclThread; // = null; +  protected CardChannel channel; // = newCardChannel(this);    protected List<AbstractAppl> applications = new ArrayList<AbstractAppl>();    public CardEmul() {      super();    } -  protected abstract CardChannelEmul newCardChannel(CardEmul cardEmul); +//  protected abstract CardChannelEmul newCardChannel(CardEmul cardEmul);    @Override    public void beginExclusive() throws CardException { @@ -71,9 +71,9 @@ public abstract class CardEmul extends Card {    @Override    public void disconnect(boolean reset) throws CardException { -    if (reset) { -      channel = newCardChannel(this); -    } +//    if (reset) { +//      channel = newCardChannel(this); +//    }    }    @Override @@ -93,7 +93,7 @@ public abstract class CardEmul extends Card {        }    public AbstractAppl getApplication(byte[] fid) { -     +      for(AbstractAppl appl : applications) {        if (Arrays.equals(appl.getAID(), fid) || Arrays.equals(appl.getFID(), fid)) {          return appl; diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java index b3bd07ab..44e48836 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java @@ -16,12 +16,14 @@  */  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.pin.gui.CancelPINProvider; +import at.gv.egiz.smcc.pin.gui.InterruptPINProvider; +import at.gv.egiz.smcc.pin.gui.CancelChangePINProvider;  import static org.junit.Assert.*;  import java.io.ByteArrayInputStream;  import java.io.IOException;  import java.io.UnsupportedEncodingException; -import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException;  import java.util.Arrays;  import java.util.List; @@ -32,119 +34,15 @@ import org.junit.Test;  import at.gv.egiz.smcc.SignatureCard.KeyboxName;  import at.gv.egiz.smcc.acos.A04ApplDEC; +import at.gv.egiz.smcc.pin.gui.DummyPINGUI; +import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.PINGUI; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; +import org.junit.Ignore;  @SuppressWarnings("restriction")  public abstract class CardTest { -  public class TestPINProvider implements PINProvider { -     -    int provided = 0; -   -    char[] pin; -   -    public TestPINProvider(char[] pin) { -      super(); -      this.pin = pin; -    } -   -    @Override -    public char[] providePIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      provided++; -      return pin; -    } - -    public int getProvided() { -      return provided; -    } -   -  } - -  public class TestChangePINProvider extends TestPINProvider implements -      ChangePINProvider { -   -    char[] oldPin; -   -    public TestChangePINProvider(char[] oldPin, char[] pin) { -      super(pin); -      this.oldPin = oldPin; -    } -   -    @Override -    public char[] provideOldPIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      return oldPin; -    } -   -  } - -  public class TestInvalidPINProvider implements PINProvider { - -    int provided = 0; -    int numWrongTries = 0; - -    char[] pin; - -    public TestInvalidPINProvider(char[] pin, int numWrongTries) { -      super(); -      this.pin = pin; -      this.numWrongTries = numWrongTries; -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      if (provided >= numWrongTries) { -        throw new CancelledException("Number of wrong tries reached: " + provided); -      } else { -        provided++; -        return pin; -      } -    } - -    public int getProvided() { -      return provided; -    } -  } - -  public class TestInvalidChangePINProvider implements ChangePINProvider { - -    int provided = 0; -    int numWrongTries = 0; - -    char[] pin; -    char[] oldPin; - -    /** emulate ChangePinProvider */ -    public TestInvalidChangePINProvider(char[] oldPin, char[] newPin, int numWrongTries) { -      super(); -      this.pin = newPin; -      this.oldPin = oldPin; -      this.numWrongTries = numWrongTries; -    } - -    @Override -    public char[] providePIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      return pin; -    } - -    public int getProvided() { -      return provided; -    } - -    @Override -    public char[] provideOldPIN(PINSpec spec, int retries) -        throws CancelledException, InterruptedException { -      if (provided >= numWrongTries) { -        throw new CancelledException("Number of wrong tries reached: " + provided); -      } else { -        provided++; -        return oldPin; -      } -    } -  } -    public CardTest() {      super();    } @@ -167,7 +65,7 @@ public abstract class CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider(pin); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin);      byte[] idlink = signatureCard.getInfobox("IdentityLink",          pinProvider, null); @@ -184,13 +82,7 @@ public abstract class CardTest {          SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new CancelledException(); -          } -        }; +        PINGUI pinProvider = new CancelPINProvider();      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, pinProvider, @@ -205,13 +97,7 @@ public abstract class CardTest {          SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new CancelledException(); -          } -        }; +        PINGUI pinProvider = new CancelPINProvider();          signatureCard.createSignature(new ByteArrayInputStream("MOCCA"              .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -226,13 +112,7 @@ public abstract class CardTest {          SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new InterruptedException(); -          } -        }; +        PINGUI pinProvider = new InterruptPINProvider();          signatureCard.createSignature(new ByteArrayInputStream("MOCCA"              .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -247,13 +127,7 @@ public abstract class CardTest {          SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new InterruptedException(); -          } -        }; +        PINGUI pinProvider = new InterruptPINProvider();          signatureCard.createSignature(new ByteArrayInputStream("MOCCA"              .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -268,11 +142,11 @@ public abstract class CardTest {          final SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { +        PINGUI pinProvider = new DummyPINGUI() {            @Override            public char[] providePIN(PINSpec spec, int retries)                throws CancelledException, InterruptedException { -       +              try {                signatureCard.getCertificate(KeyboxName.SECURE_SIGNATURE_KEYPAIR);                assertTrue(false); @@ -281,10 +155,10 @@ public abstract class CardTest {                // expected                throw new CancelledException();              } -       +            }          }; -       +          signatureCard.createSignature(new ByteArrayInputStream("MOCCA"              .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR,              pinProvider, null); @@ -298,7 +172,7 @@ public abstract class CardTest {          final SignatureCard signatureCard = createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { +        PINGUI pinProvider = new DummyPINGUI() {            @Override            public char[] providePIN(PINSpec spec, int retries)                throws CancelledException, InterruptedException { @@ -311,7 +185,6 @@ public abstract class CardTest {                // expected                throw new CancelledException();              } -                  }          }; @@ -339,13 +212,7 @@ public abstract class CardTest {          PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); -        PINProvider pinProvider = new PINProvider() { -          @Override -          public char[] providePIN(PINSpec spec, int retries) -              throws CancelledException, InterruptedException { -            throw new CancelledException(); -          } -        }; +        ModifyPINGUI pinProvider = new CancelChangePINProvider();          List<PINSpec> specs = signatureCard.getPINSpecs(); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/PIN.java b/smcc/src/test/java/at/gv/egiz/smcc/PIN.java index ae883727..2cda0c2f 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/PIN.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/PIN.java @@ -23,19 +23,23 @@ public class PIN {    public static final int STATE_PIN_VERIFIED = 1;    public static final int STATE_PIN_BLOCKED = -1; + +  public static final int STATE_PIN_NOTACTIVE = 2;    public byte[] pin;    public int kid; -  public int state = STATE_RESET; +  public int state; // = STATE_RESET; -  public int kfpc = 10; +  public int kfpc; // = 10; -  public PIN(byte[] pin, int kid, int kfpc) { +  //TODO also provde default constructor without state param +  public PIN(byte[] pin, int kid, int kfpc, int state) {      this.pin = pin;      this.kid = kid;      this.kfpc = kfpc; +    this.state = state;    }  } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java index 9fd96d73..f4ac5c35 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03ApplDEC.java @@ -40,7 +40,7 @@ public class A03ApplDEC extends ACOSApplDEC {      putFile(new File(FID_EF_INFOBOX, EF_INFOBOX, FCI_EF_INFOBOX, KID_PIN_INF));      try { -      pins.put(KID_PIN_INF, new PIN("0000\0\0\0\0".getBytes("ASCII"), KID_PIN_INF, 10)); +      pins.put(KID_PIN_INF, new PIN("0000\0\0\0\0".getBytes("ASCII"), KID_PIN_INF, 10, PIN.STATE_RESET));      } catch (UnsupportedEncodingException e) {        throw new RuntimeException(e);      } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java index 58216b6b..7394bae7 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardEmul.java @@ -24,13 +24,8 @@ import at.gv.egiz.smcc.CardEmul;  public class A03CardEmul extends ACOSCardEmul {    public A03CardEmul(A03ApplSIG applSIG, A03ApplDEC applDEC) { +    channel = new A03CardChannelEmul(this);      applications.add(applSIG);      applications.add(applDEC);    } - -  @Override -  protected CardChannelEmul newCardChannel(CardEmul cardEmul) { -    return new A03CardChannelEmul(this); -  } -  } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java index 776c0370..3a8ac41c 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A03CardTest.java @@ -22,15 +22,16 @@ import java.util.Arrays;  import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard;  import at.gv.egiz.smcc.CancelledException;  import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.CardNotSupportedException;  import at.gv.egiz.smcc.CardTerminalEmul; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider;  import at.gv.egiz.smcc.LockedException;  import at.gv.egiz.smcc.NotActivatedException;  import at.gv.egiz.smcc.PINFormatException;  import at.gv.egiz.smcc.PINMgmtSignatureCard; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider;  import at.gv.egiz.smcc.PINSpec;  import at.gv.egiz.smcc.SignatureCard;  import at.gv.egiz.smcc.SignatureCardException; @@ -74,12 +75,12 @@ public class A03CardTest extends ACOSCardTest {        char[] pin = defaultPin;        for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(pin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin));          char[] newPin = new char[i];          Arrays.fill(newPin, '0');          signatureCard -            .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); +            .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin));          pin = newPin;        } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java index 70925aa6..dd44d05b 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardEmul.java @@ -24,14 +24,9 @@ import at.gv.egiz.smcc.CardEmul;  public class A04CardEmul extends ACOSCardEmul {    public A04CardEmul(A04ApplSIG applSIG, A04ApplDEC applDEC) { +    channel = new A04CardChannelEmul(this);      applications.add(applSIG);      applications.add(applDEC);    } - -  @Override -  protected CardChannelEmul newCardChannel(CardEmul cardEmul) { -    return new A04CardChannelEmul(this); -  } -  } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java index d15e80d7..1cbea1b3 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/A04CardTest.java @@ -28,7 +28,6 @@ import java.util.Arrays;  import org.junit.BeforeClass;  import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard;  import at.gv.egiz.smcc.CancelledException;  import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.CardNotSupportedException; @@ -41,7 +40,8 @@ import at.gv.egiz.smcc.PINSpec;  import at.gv.egiz.smcc.SignatureCard;  import at.gv.egiz.smcc.SignatureCardException;  import at.gv.egiz.smcc.SignatureCardFactory; -import at.gv.egiz.smcc.CardTest.TestPINProvider; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider;  public class A04CardTest extends ACOSCardTest { @@ -88,8 +88,8 @@ public class A04CardTest extends ACOSCardTest {          char[] newPin = new char[i];          Arrays.fill(newPin, '0');          signatureCard -            .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); +            .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin));          pin = newPin;        } @@ -111,7 +111,7 @@ public class A04CardTest extends ACOSCardTest {      SignatureCard signatureCard = factory.createSignatureCard(card,          new CardTerminalEmul(card)); -    TestPINProvider pinProvider = new TestPINProvider(pin); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin);      byte[] idlink = signatureCard.getInfobox("IdentityLink",          pinProvider, null); @@ -129,7 +129,7 @@ public class A04CardTest extends ACOSCardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider(pin); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider(pin);      byte[] idlink = signatureCard.getInfobox("IdentityLink",          pinProvider, null); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java index 08979536..09a754f3 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplDEC.java @@ -297,7 +297,7 @@ public abstract class ACOSApplDEC extends ACOSAppl {      System.arraycopy(C_CH_EKEY, 0, EF_C_CH_EKEY, 0, C_CH_EKEY.length);      putFile(new File(FID_EF_C_CH_EKEY, EF_C_CH_EKEY, FCI_EF_C_CH_EKEY));      try { -      pins.put(KID_PIN_DEC, new PIN("1234\0\0\0\0".getBytes("ASCII"), KID_PIN_DEC, 10)); +      pins.put(KID_PIN_DEC, new PIN("1234\0\0\0\0".getBytes("ASCII"), KID_PIN_DEC, 10, PIN.STATE_RESET));      } catch (UnsupportedEncodingException e) {        throw new RuntimeException(e);      } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java index e476b434..6ab5903a 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSApplSIG.java @@ -221,7 +221,7 @@ public abstract class ACOSApplSIG extends ACOSAppl {      // PINs      try { -      pins.put(KID_PIN_SIG, new PIN(Arrays.copyOf("123456".getBytes("ASCII"), 8), KID_PIN_SIG, 3)); +      pins.put(KID_PIN_SIG, new PIN(Arrays.copyOf("123456".getBytes("ASCII"), 8), KID_PIN_SIG, 3, PIN.STATE_RESET));      } catch (UnsupportedEncodingException e) {        throw new RuntimeException(e);      } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java index 56d1e4b2..4f012739 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java @@ -16,26 +16,23 @@  */  package at.gv.egiz.smcc.acos; -import static org.junit.Assert.assertEquals;  import static org.junit.Assert.assertNotNull;  import static org.junit.Assert.assertNull;  import static org.junit.Assert.assertTrue;  import java.io.ByteArrayInputStream;  import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException;  import java.util.Arrays;  import org.junit.Test; -import at.gv.egiz.smcc.ACOSCard;  import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.CardNotSupportedException;  import at.gv.egiz.smcc.CardTest;  import at.gv.egiz.smcc.LockedException;  import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider;  import at.gv.egiz.smcc.SignatureCard;  import at.gv.egiz.smcc.SignatureCardException;  import at.gv.egiz.smcc.SignatureCard.KeyboxName; @@ -60,7 +57,7 @@ public abstract class ACOSCardTest extends CardTest {      appl.clearInfobox();      byte[] idlink = signatureCard.getInfobox("IdentityLink", -        new TestPINProvider(pin), null); +        new SMCCTestPINProvider(pin), null);      assertNull(idlink);    } @@ -76,7 +73,7 @@ public abstract class ACOSCardTest extends CardTest {      ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC);      appl.setInfoboxHeader((byte) 0xFF); -    signatureCard.getInfobox("IdentityLink", new TestPINProvider(pin), null); +    signatureCard.getInfobox("IdentityLink", new SMCCTestPINProvider(pin), null);    } @@ -138,7 +135,7 @@ public abstract class ACOSCardTest extends CardTest {      byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), -        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); +        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new SMCCTestPINProvider(pin), null);      assertNotNull(signature); @@ -158,7 +155,7 @@ public abstract class ACOSCardTest extends CardTest {      byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), -        KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); +        KeyboxName.CERITIFIED_KEYPAIR, new SMCCTestPINProvider(pin), null);      assertNotNull(signature); @@ -171,7 +168,7 @@ public abstract class ACOSCardTest extends CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -186,7 +183,7 @@ public abstract class ACOSCardTest extends CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -204,7 +201,7 @@ public abstract class ACOSCardTest extends CardTest {      ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG);      appl.setPin(ACOSApplSIG.KID_PIN_SIG, null); -    TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -222,7 +219,7 @@ public abstract class ACOSCardTest extends CardTest {      ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC);      appl.setPin(ACOSApplDEC.KID_PIN_DEC, null); -    TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java new file mode 100644 index 00000000..dffe7e29 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelChangePINProvider.java @@ -0,0 +1,39 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class CancelChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + +  public CancelChangePINProvider() { +  } + +  @Override +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    throw new CancelledException("cancelled by cancelPINProvider"); +  } + +  @Override +  public char[] provideNewPIN(PINSpec spec) +          throws CancelledException, InterruptedException { +    throw new CancelledException("cancelled by cancelPINProvider"); +  } + +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java new file mode 100644 index 00000000..77f19345 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class CancelPINProvider extends DummyPINGUI implements PINGUI { + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    throw new CancelledException("cancelled by cancelPINProvider"); +  } +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java new file mode 100644 index 00000000..5eb8b9a1 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/ChangePINProvider.java @@ -0,0 +1,49 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class ChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + +  int provided = 0; +  char[] pin; +  char[] oldPin; + +  public ChangePINProvider(char[] oldPin, char[] pin) { +    this.pin = pin; +    this.oldPin = oldPin; +  } + +  public int getProvided() { +    return provided; +  } + +  @Override +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    provided++; +    return oldPin; +  } + +  @Override +  public char[] provideNewPIN(PINSpec spec) { +    return pin; +  } + +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java new file mode 100644 index 00000000..fff89409 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyChangePINGUI.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public abstract class DummyChangePINGUI implements ModifyPINGUI { + +  @Override +  public void validKeyPressed() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void correctionButtonPressed() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void allKeysCleared() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void finish() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void finishDirect() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void modifyPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void enterCurrentPIN(PINSpec spec, int retries) { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void enterNewPIN(PINSpec spec) { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void confirmNewPIN(PINSpec spec) { +    throw new UnsupportedOperationException("Not supported yet."); +  } +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java new file mode 100644 index 00000000..4d99b5c1 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/DummyPINGUI.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public abstract class DummyPINGUI implements PINGUI { + +   @Override +  public void enterPINDirect(PINSpec spec, int retries) throws CancelledException, InterruptedException { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void enterPIN(PINSpec spec, int retries) throws CancelledException, InterruptedException { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void validKeyPressed() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void correctionButtonPressed() { +    throw new UnsupportedOperationException("Not supported yet."); +  } + +  @Override +  public void allKeysCleared() { +    throw new UnsupportedOperationException("Not supported yet."); +  } +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java new file mode 100644 index 00000000..5706b888 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +@SuppressWarnings("restriction") +public class InterruptPINProvider extends DummyPINGUI implements PINGUI { + +  public InterruptPINProvider() { +  } + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    throw new InterruptedException("interrupted by cancelPINProvider"); +  } + +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java new file mode 100644 index 00000000..69c9f42a --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidChangePINProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class InvalidChangePINProvider extends DummyChangePINGUI implements ModifyPINGUI { + +  int provided = 0; +  int numWrongTries = 0; +  char[] pin; +  char[] oldPin; + +  /** emulate ChangePinProvider */ +  public InvalidChangePINProvider(char[] oldPin, char[] newPin, int numWrongTries) { +    super(); +    this.pin = newPin; +    this.oldPin = oldPin; +    this.numWrongTries = numWrongTries; +  } + +  @Override +  public char[] provideCurrentPIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    if (provided >= numWrongTries) { +      throw new CancelledException("Number of wrong tries reached: " + provided); +    } else { +      provided++; +      return oldPin; +    } +  } + +  public int getProvided() { +    return provided; +  } + +  @Override +  public char[] provideNewPIN(PINSpec spec) { +    return pin; +  } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java new file mode 100644 index 00000000..db01fd0d --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class InvalidPINProvider extends DummyPINGUI implements PINGUI { + +  int provided = 0; +  int numWrongTries = 0; +  char[] pin; + +  public InvalidPINProvider(char[] pin, int numWrongTries) { +    super(); +    this.pin = pin; +    this.numWrongTries = numWrongTries; +  } + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    if (provided >= numWrongTries) { +      throw new CancelledException("Number of wrong tries reached: " + provided); +    } else { +      provided++; +      return pin; +    } +  } + +  public int getProvided() { +    return provided; +  } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java new file mode 100644 index 00000000..dffc90d7 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java @@ -0,0 +1,43 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.pin.gui; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PINSpec; + +public class SMCCTestPINProvider extends DummyPINGUI implements PINGUI { + +  public int provided = 0; +  char[] pin; + +  public SMCCTestPINProvider(char[] pin) { +    this.pin = pin; +  } + +  @Override +  public char[] providePIN(PINSpec spec, int retries) +          throws CancelledException, InterruptedException { +    provided++; +    return pin; +  } + +  public int getProvided() { +    return provided; +  } + +  +}
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java index 2ca63eea..62528e6e 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSAppl.java @@ -69,27 +69,4 @@ public abstract class STARCOSAppl extends AbstractAppl implements CardAppl {        pin.next().state = PIN.STATE_RESET;      }    } -   -  public void setPin(int kid, char[] value) { -    PIN pin = pins.get(kid); -    if (pin != null) { -      if (value == null) { -        pin.pin = null; -      } else { -        byte[] b = new byte[8]; -        b[0] = (byte) (0x20 | value.length); -        for(int i = 1, j = 0; i < b.length; i++) { -          int h = ((j < value.length)  -                  ? Character.digit(value[j++], 10)  -                  : 0x0F); -          int l = ((j < value.length)  -                  ? Character.digit(value[j++], 10)  -                  : 0x0F); -          b[i] = (byte) ((h << 4) | l); -        } -        pin.pin = b; -      } -    } -  } -  } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java index cec305da..8741dd2d 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplGewoehnlicheSignatur.java @@ -16,7 +16,6 @@  */  package at.gv.egiz.smcc.starcos; -import java.io.UnsupportedEncodingException;  import java.util.Arrays;  import java.util.Random; @@ -200,12 +199,18 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl {    protected byte[] EF_C_X509_CH_AUT = new byte[2000]; -   -  public STARCOSApplGewoehnlicheSignatur(STARCOSCardChannelEmul channel) { + +  protected byte[] dst; + +  public static final byte[] DST = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10}; +  public static final byte[] DST_G3 = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x80, (byte) 0x01, (byte) 0x04 }; + +  public STARCOSApplGewoehnlicheSignatur(STARCOSCardChannelEmul channel, byte[] dst) {      super(channel);      // Files      System.arraycopy(C_X509_CH_AUT, 0, EF_C_X509_CH_AUT, 0, C_X509_CH_AUT.length);      putFile(new File(FID_EF_C_X509_CH_AUT, EF_C_X509_CH_AUT, FCI_EF_C_X509_CH_AUT)); +    this.dst = dst;    }    @Override @@ -240,12 +245,19 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl {        case 0x81:          // EXTERNAL AUTHENTICATE        } +    case 0xAA: +      switch (command.getP1()) { +      case 0x41:  +        if (Arrays.equals(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x10}, command.getData())) { +          return new ResponseAPDU(new byte[] {(byte) 0x90, (byte) 0x00}); +        } +      default: +        return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x80}); +      }      case 0xB6:        switch (command.getP1()) {        case 0x41: {          // PSO - COMPUTE DIGITAL SIGNATURE -        byte[] dst = new byte[] { (byte) 0x84, (byte) 0x03, (byte) 0x80, -            (byte) 0x02, (byte) 0x00, (byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10};          if (Arrays.equals(dst, command.getData())) {            securityEnv = command.getData();            return new ResponseAPDU(new byte[] {(byte) 0x90, (byte) 0x00}); @@ -328,5 +340,10 @@ public class STARCOSApplGewoehnlicheSignatur extends STARCOSAppl {    } +  @Override +  public void setPin(int kid, char[] value) { +    throw new UnsupportedOperationException("Not supported yet."); +  } +  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java index b7835a43..c470351a 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplInfobox.java @@ -156,5 +156,10 @@ public class STARCOSApplInfobox extends STARCOSAppl {      throw new CardException("Not supported.");    } +  @Override +  public void setPin(int kid, char[] value) { +    throw new UnsupportedOperationException("Not supported yet."); +  } +  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java index 9fb5ad37..4036ca41 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSApplSichereSignatur.java @@ -213,16 +213,14 @@ public class STARCOSApplSichereSignatur extends STARCOSAppl {    protected byte[] EF_C_X509_CH_DS = new byte[2000]; -  public STARCOSApplSichereSignatur(STARCOSCardChannelEmul channel) { +  public STARCOSApplSichereSignatur(STARCOSCardChannelEmul channel, byte[] SS_pin, int pinState) {      super(channel);      // Files      System.arraycopy(C_X509_CH_DS, 0, EF_C_X509_CH_DS, 0, C_X509_CH_DS.length);      putFile(new File(FID_EF_C_X509_CH_DS, EF_C_X509_CH_DS, FCI_EF_C_X509_CH_DS));      // PINs -    pins.put(KID_PIN_SS, new PIN(new byte[] { (byte) 0x24, (byte) 0x12, -        (byte) 0x34, (byte) 0x56, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, -        (byte) 0xFF }, KID_PIN_SS, 3)); +    pins.put(KID_PIN_SS, new PIN(SS_pin, KID_PIN_SS, 3, pinState));    }    @Override @@ -344,4 +342,34 @@ public class STARCOSApplSichereSignatur extends STARCOSAppl {    } +  /** +   * set and activate pin +   * @param value if null, pin will be set to NOTACTIVE +   */ +  @Override +  public void setPin(int kid, char[] value) { +    PIN pin = pins.get(kid); +    if (pin != null) { +      if (value == null) { +//        pin.pin = null; +        //TransportPIN +//        pin.pin = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +        pin.state = PIN.STATE_PIN_NOTACTIVE; +      } else { +        byte[] b = new byte[8]; +        b[0] = (byte) (0x20 | value.length); +        for(int i = 1, j = 0; i < b.length; i++) { +          int h = ((j < value.length) +                  ? Character.digit(value[j++], 10) +                  : 0x0F); +          int l = ((j < value.length) +                  ? Character.digit(value[j++], 10) +                  : 0x0F); +          b[i] = (byte) ((h << 4) | l); +        } +        pin.pin = b; +        pin.state = PIN.STATE_RESET; +      } +    } +  }  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java index 89030894..2e0c54eb 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardChannelEmul.java @@ -16,7 +16,6 @@  */  package at.gv.egiz.smcc.starcos; -import java.io.UnsupportedEncodingException;  import java.util.Arrays;  import java.util.HashMap; @@ -30,6 +29,8 @@ import at.gv.egiz.smcc.CardChannelEmul;  import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.File;  import at.gv.egiz.smcc.PIN; +import java.util.ArrayList; +import java.util.List;  @SuppressWarnings("restriction")  public class STARCOSCardChannelEmul extends CardChannelEmul { @@ -40,14 +41,13 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {     *      */    protected CardEmul cardEmul; -   + +  public final List<File> globalFiles = new ArrayList<File>();    public final HashMap<Integer, PIN> globalPins = new HashMap<Integer, PIN>(); -  public STARCOSCardChannelEmul(CardEmul cardEmul) { +  public STARCOSCardChannelEmul(CardEmul cardEmul, byte[] Glob_PIN, int PIN_STATE) {      this.cardEmul = cardEmul; -    globalPins.put(KID_PIN_Glob, new PIN(new byte[] { (byte) 0x24, (byte) 0x00, -        (byte) 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, -        (byte) 0xFF }, KID_PIN_Glob, 10)); +    globalPins.put(KID_PIN_Glob, new PIN(Glob_PIN, KID_PIN_Glob, 10, PIN_STATE));   }    @Override @@ -88,6 +88,21 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {            }          }          return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x82}); +      } else if (globalFiles != null) { +        if (command.getP2() != 0x04) { +          throw new CardException("Not supported."); +        } +        for (File file : globalFiles) { +          if (Arrays.equals(fid, file.fid)) { +            currentFile = file; +            byte[] response = new byte[file.fcx.length + 2]; +            System.arraycopy(file.fcx, 0, response, 0, file.fcx.length); +            response[file.fcx.length] = (byte) 0x90; +            response[file.fcx.length + 1] = (byte) 0x00; +            return new ResponseAPDU(response); +          } +        } +        return new ResponseAPDU(new byte[] {(byte) 0x6A, (byte) 0x82});        } else {          throw new CardException("Not supported.");        } @@ -121,6 +136,23 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {    } +  protected ResponseAPDU cmdREAD_RECORD(CommandAPDU command) throws CardException { +    if (command.getINS() != 0xB2) { +      throw new IllegalArgumentException("INS has to be 0xB2"); +    } +    if (currentFile == null) { +      return new ResponseAPDU(new byte[]{ (byte) 0x69, (byte) 0x86 }); +    } +    if (command.getP1() != 0x01 || command.getP2() != 0x04) { +      throw new CardException("Not implemented."); +    } +    byte[] response = new byte[currentFile.file.length + 2]; +    System.arraycopy(currentFile.file, 0, response, 0, currentFile.file.length); +    response[currentFile.file.length] = (byte) 0x90; +    response[currentFile.file.length + 1] = (byte) 0x00; +    return new ResponseAPDU(response); +  } +    protected ResponseAPDU cmdREAD_BINARY(CommandAPDU command) throws CardException {      if (command.getINS() != 0xB0) { @@ -192,6 +224,10 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {        case 0xB0:          return cmdREAD_BINARY(command); +      // READ RECORD +      case 0xB2: +        return cmdREAD_RECORD(command); +        // VERIFY        case 0x20:          return cmdVERIFY(command); @@ -248,9 +284,15 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {      }      if (pin != null) { -   -      if (reference.length == 0) { -        return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) (pin.kfpc | 0xC0)}); + +      if (reference == null || reference.length == 0) { +        if (pin.state == PIN.STATE_PIN_NOTACTIVE) { +          return new ResponseAPDU(new byte[] { (byte) 0x69, (byte) 0x84 }); +        } else if (pin.state == PIN.STATE_PIN_BLOCKED) { +          return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) 0xc0 }); +        } else { +          return new ResponseAPDU(new byte[] { (byte) 0x63, (byte) (pin.kfpc | 0xC0)}); +        }        }        if (reference.length != 8) { @@ -264,7 +306,7 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {          case PIN.STATE_RESET:            pin.state = PIN.STATE_PIN_VERIFIED; -           +          default:            pin.kfpc = 10;            return new ResponseAPDU(new byte[] { (byte) 0x90, (byte) 0x00 }); @@ -321,7 +363,20 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {          return new ResponseAPDU(new byte[] {(byte) 0x67, (byte) 0x00});        } -      response = verifyPin(0xFF & command.getP2(), data); +      PIN pin; +      if (currentAppl != null) { +        pin = currentAppl.pins.get(command.getP2()); +      } else { +        pin = globalPins.get(command.getP2()); +      } +      if (pin.state == PIN.STATE_PIN_NOTACTIVE) { +        pin.pin = data; +        pin.state = PIN.STATE_RESET; +        response = new ResponseAPDU(new byte[] { (byte) 0x90, (byte) 0x00 }); +      } else { +        // P1 == 0x01 not allowed on active pin (?) +        response = new ResponseAPDU(new byte[] { (byte) 0x6A, (byte) 0x86}); +      }      } else if (command.getP1() == 0x00) { @@ -330,21 +385,22 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {        }        response = verifyPin(0xFF & command.getP2(), Arrays.copyOf(data, 8)); -     + +      if (response.getSW() == 0x9000) { +        PIN pin; +        if (currentAppl != null) { +          pin = currentAppl.pins.get(command.getP2()); +        } else { +          pin = globalPins.get(command.getP2()); +        } +        pin.pin = Arrays.copyOfRange(data, 8, 16); +        pin.state = PIN.STATE_PIN_VERIFIED; +      } +      } else {        return new ResponseAPDU(new byte[] { (byte) 0x6A, (byte) 0x81 });      } -    if (response.getSW() == 0x9000) { -      PIN pin; -      if (currentAppl != null) { -        pin = currentAppl.pins.get(command.getP2()); -      } else { -        pin = globalPins.get(command.getP2()); -      } -      pin.pin = Arrays.copyOfRange(data, 8, 16); -    } -      return response;    } @@ -353,7 +409,10 @@ public class STARCOSCardChannelEmul extends CardChannelEmul {      PIN pin = globalPins.get(kid);      if (pin != null) {        if (value == null) { -        pin.pin = null; +//        pin.pin = null; +        //TransportPIN +//        pin.pin = new byte[] { (byte) 0x24, (byte) 0x12, (byte) 0x34, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +        pin.state = PIN.STATE_PIN_NOTACTIVE;        } else {          byte[] b = new byte[8];          b[0] = (byte) (0x20 | value.length); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java index 7b2f3fbe..5963fb63 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardEmul.java @@ -21,30 +21,34 @@ import javax.smartcardio.ATR;  import at.gv.egiz.smcc.CardChannelEmul;  import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.PIN;  @SuppressWarnings("restriction")  public class STARCOSCardEmul extends CardEmul { -   + +  public static byte[] DEFAULT_SS_PIN = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +  public static byte[] DEFAULT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +    protected static ATR ATR = new ATR(new byte[] {        (byte) 0x3b, (byte) 0xbd, (byte) 0x18, (byte) 0x00, (byte) 0x81, (byte) 0x31, (byte) 0xfe, (byte) 0x45,         (byte) 0x80, (byte) 0x51, (byte) 0x02, (byte) 0x67, (byte) 0x05, (byte) 0x18, (byte) 0xb1, (byte) 0x02,         (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x81, (byte) 0x05, (byte) 0x31    }); -   +    public STARCOSCardEmul() { -    applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel)); +    this(DEFAULT_SS_PIN, DEFAULT_Glob_PIN, PIN.STATE_RESET); +  } + +  public STARCOSCardEmul(byte[] SS_PIN, byte[] Glob_PIN, int PIN_STATE) { +    channel = new STARCOSCardChannelEmul(this, Glob_PIN, PIN_STATE); +    applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel, SS_PIN, PIN_STATE));      applications.add(new STARCOSApplInfobox((STARCOSCardChannelEmul) channel)); -    applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel)); +    applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel, +            STARCOSApplGewoehnlicheSignatur.DST));    }    @Override    public ATR getATR() {      return ATR;    } - -  @Override -  protected CardChannelEmul newCardChannel(CardEmul cardEmul) { -    return new STARCOSCardChannelEmul(this); -  } -  }
\ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java index b7dc9a0c..154884d4 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java @@ -22,12 +22,9 @@ import static org.junit.Assert.assertTrue;  import java.io.ByteArrayInputStream;  import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest;  import java.security.NoSuchAlgorithmException;  import java.util.Arrays; -import javax.smartcardio.CardChannel;  import org.junit.Test; @@ -36,25 +33,20 @@ import at.gv.egiz.smcc.CardEmul;  import at.gv.egiz.smcc.CardNotSupportedException;  import at.gv.egiz.smcc.CardTerminalEmul;  import at.gv.egiz.smcc.CardTest; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.pin.gui.InvalidChangePINProvider; +import at.gv.egiz.smcc.pin.gui.InvalidPINProvider;  import at.gv.egiz.smcc.LockedException;  import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PIN;  import at.gv.egiz.smcc.PINFormatException;  import at.gv.egiz.smcc.PINMgmtSignatureCard;  import at.gv.egiz.smcc.PINSpec; -import at.gv.egiz.smcc.STARCOSCard;  import at.gv.egiz.smcc.SignatureCard;  import at.gv.egiz.smcc.SignatureCardException;  import at.gv.egiz.smcc.SignatureCardFactory; -import at.gv.egiz.smcc.CardTest.TestChangePINProvider; -import at.gv.egiz.smcc.CardTest.TestPINProvider; -import at.gv.egiz.smcc.PINProvider; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider;  import at.gv.egiz.smcc.SignatureCard.KeyboxName; -import at.gv.egiz.smcc.acos.A03ApplDEC; -import at.gv.egiz.smcc.acos.A04ApplDEC; -import at.gv.egiz.smcc.acos.A04ApplSIG; -import at.gv.egiz.smcc.acos.ACOSAppl; -import at.gv.egiz.smcc.acos.ACOSApplDEC; -import at.gv.egiz.smcc.acos.ACOSApplSIG;  import org.junit.Ignore;  public class STARCOSCardTest extends CardTest { @@ -69,7 +61,17 @@ public class STARCOSCardTest extends CardTest {      assertTrue(signatureCard instanceof PINMgmtSignatureCard);      return signatureCard;    } -   + +  protected SignatureCard createSignatureCard(byte[] SS_PIN, byte[] Glob_PIN, int pinState) +      throws CardNotSupportedException { +    SignatureCardFactory factory = SignatureCardFactory.getInstance(); +    STARCOSCardEmul card = new STARCOSCardEmul(SS_PIN, Glob_PIN, pinState); +    SignatureCard signatureCard = factory.createSignatureCard(card, +        new CardTerminalEmul(card)); +    assertTrue(signatureCard instanceof PINMgmtSignatureCard); +    return signatureCard; +  } +    @Test    public void testGetInfoboxIdentityLinkEmpty() throws SignatureCardException,        InterruptedException, CardNotSupportedException { @@ -82,7 +84,7 @@ public class STARCOSCardTest extends CardTest {      appl.clearInfobox();      byte[] idlink = signatureCard.getInfobox("IdentityLink", -        new TestPINProvider(pin), null); +        new SMCCTestPINProvider(pin), null);      assertNull(idlink);    } @@ -98,10 +100,10 @@ public class STARCOSCardTest extends CardTest {      STARCOSApplInfobox appl = (STARCOSApplInfobox) card.getApplication(STARCOSAppl.AID_Infobox);      appl.setInfoboxHeader((byte) 0xFF); -    signatureCard.getInfobox("IdentityLink", new TestPINProvider(pin), null); +    signatureCard.getInfobox("IdentityLink", new SMCCTestPINProvider(pin), null);    } -  +    @Test    public void testGetCerts() throws SignatureCardException,        InterruptedException, CardNotSupportedException { @@ -145,7 +147,7 @@ public class STARCOSCardTest extends CardTest {      signatureCard.getCertificate(KeyboxName.CERITIFIED_KEYPAIR);    } -   +    @Test    public void testSignSichereSignatur() throws SignatureCardException,        InterruptedException, CardNotSupportedException, @@ -160,7 +162,7 @@ public class STARCOSCardTest extends CardTest {      byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), -        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); +        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new SMCCTestPINProvider(pin), null);      assertNotNull(signature); @@ -180,12 +182,12 @@ public class STARCOSCardTest extends CardTest {      byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), -        KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); +        KeyboxName.CERITIFIED_KEYPAIR, new SMCCTestPINProvider(pin), null);      assertNotNull(signature);    } -   +    @Test(expected = LockedException.class)    public void testSignSichereSignaturInvalidPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, @@ -193,7 +195,7 @@ public class STARCOSCardTest extends CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, @@ -208,7 +210,7 @@ public class STARCOSCardTest extends CardTest {      SignatureCard signatureCard = createSignatureCard(); -    TestPINProvider pinProvider = new TestPINProvider("1234".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("1234".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, @@ -221,12 +223,9 @@ public class STARCOSCardTest extends CardTest {        InterruptedException, CardNotSupportedException,        NoSuchAlgorithmException, IOException { -    SignatureCard signatureCard = createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); -    appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, null); +    SignatureCard signatureCard = createSignatureCard(null, null, PIN.STATE_PIN_BLOCKED); -    TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("000000".toCharArray());      assertTrue(pinProvider.getProvided() <= 0);      signatureCard.createSignature(new ByteArrayInputStream("MOCCA" @@ -240,68 +239,79 @@ public class STARCOSCardTest extends CardTest {        InterruptedException, CardNotSupportedException,        NoSuchAlgorithmException, IOException { -    SignatureCard signatureCard = createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); -    channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, null); - -    TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); +    SignatureCard signatureCard = createSignatureCard(null, null, PIN.STATE_PIN_BLOCKED); +     +    SMCCTestPINProvider pinProvider = new SMCCTestPINProvider("0000".toCharArray());      signatureCard.createSignature(new ByteArrayInputStream("MOCCA"          .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR,          pinProvider, null);    } -   +    @Test    public void testChangePin() throws CardNotSupportedException,        LockedException, NotActivatedException, CancelledException,        PINFormatException, SignatureCardException, InterruptedException { -    char[] defaultPin = "123456".toCharArray(); - -    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); -    channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); -    STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); -    appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin); +    // set all initial pins to DEFAULT_SS_PIN (123456) +    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( +            STARCOSCardEmul.DEFAULT_SS_PIN, STARCOSCardEmul.DEFAULT_SS_PIN, PIN.STATE_RESET);      for (PINSpec pinSpec : signatureCard.getPINSpecs()) { -      char[] pin = defaultPin; +      char[] pin = "123456".toCharArray();        for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(pin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin));          char[] newPin = new char[i];          Arrays.fill(newPin, '0');          signatureCard -            .changePIN(pinSpec, new TestChangePINProvider(pin, newPin)); -        signatureCard.verifyPIN(pinSpec, new TestPINProvider(newPin)); +            .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin));          pin = newPin;        }      }    }    @Test -  public void testVerifyInvalidPin() throws CardNotSupportedException, +  @Override +  public void testActivatePin() throws CardNotSupportedException,        LockedException, NotActivatedException, CancelledException,        PINFormatException, SignatureCardException, InterruptedException { -    char[] defaultPin = "123456".toCharArray(); +    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( +            null, null, PIN.STATE_PIN_NOTACTIVE); + +    for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + +      char[] pin = "1234567890".substring(0, pinSpec.getMinLength()).toCharArray(); + +      boolean notActive = false; +      try { +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +      } catch (NotActivatedException ex) { +        notActive = true; +      } +      assertTrue(notActive); + +      signatureCard.activatePIN(pinSpec, new ChangePINProvider(null, pin)); +      signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +    } +  } + +  @Test +  public void testVerifyInvalidPin() throws CardNotSupportedException, +      LockedException, NotActivatedException, CancelledException, +      PINFormatException, SignatureCardException, InterruptedException {      PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); -    channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); -    STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); -    appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin);      for (PINSpec pinSpec : signatureCard.getPINSpecs()) {        char[] invalidPin = "999999".toCharArray();        int numInvalidTries = 2; -      TestInvalidPINProvider invalidPinProvider = new TestInvalidPINProvider(invalidPin, numInvalidTries); +      InvalidPINProvider invalidPinProvider = new InvalidPINProvider(invalidPin, numInvalidTries);        try {          signatureCard.verifyPIN(pinSpec, invalidPinProvider);        } catch (CancelledException ex) { @@ -315,21 +325,15 @@ public class STARCOSCardTest extends CardTest {    public void testChangeInvalidPin() throws CardNotSupportedException,        LockedException, NotActivatedException, CancelledException,        PINFormatException, SignatureCardException, InterruptedException { -    char[] defaultPin = "123456".toCharArray();      PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard(); -    CardEmul card = (CardEmul) signatureCard.getCard(); -    STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); -    channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, defaultPin); -    STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); -    appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, defaultPin); - +          for (PINSpec pinSpec : signatureCard.getPINSpecs()) {        char[] invalidPin = "999999".toCharArray();        int numInvalidTries = 2; -      TestInvalidChangePINProvider invalidPinProvider = -              new TestInvalidChangePINProvider(invalidPin, defaultPin, numInvalidTries); +      InvalidChangePINProvider invalidPinProvider = +              new InvalidChangePINProvider(invalidPin, invalidPin, numInvalidTries);        try {          signatureCard.changePIN(pinSpec, invalidPinProvider); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java new file mode 100644 index 00000000..dc6836ae --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardChannelEmul.java @@ -0,0 +1,46 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.starcos; + +import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.File; +import at.gv.egiz.smcc.PIN; + +/** + * + * @author clemens + */ +public class STARCOSG3CardChannelEmul extends STARCOSCardChannelEmul { + +  public STARCOSG3CardChannelEmul(CardEmul cardEmul, byte[] Glob_PIN, int PIN_STATE) { +    super(cardEmul, Glob_PIN, PIN_STATE); + +    // G3 version file +    byte[] versionFileFID = new byte[]{(byte) 0x00, (byte) 0x32}; +    byte[] versionFile = new byte[]{ +      (byte) 0xa5, (byte) 0x0e, (byte) 0x53, (byte) 0x02, (byte) 0x01, (byte) 0x20, (byte) 0x54, (byte) 0x08, +      (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x04, (byte) 0x01, (byte) 0x70, (byte) 0x01}; +    byte[] versionFileFCX = new byte[]{ +      (byte) 0x62, (byte) 0x1a, (byte) 0x80, (byte) 0x02, (byte) 0x00, (byte) 0x14, (byte) 0x82, (byte) 0x05, +      (byte) 0x44, (byte) 0x41, (byte) 0x00, (byte) 0x14, (byte) 0x01, (byte) 0x83, (byte) 0x02, (byte) 0x00, +      (byte) 0x32, (byte) 0x88, (byte) 0x01, (byte) 0xd8, (byte) 0x8a, (byte) 0x01, (byte) 0x05, (byte) 0xa1, +      (byte) 0x03, (byte) 0x8b, (byte) 0x01, (byte) 0x03}; + +    globalFiles.add(new File(versionFileFID, versionFile, versionFileFCX)); + +  } + } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java new file mode 100644 index 00000000..7583b3ad --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardEmul.java @@ -0,0 +1,57 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.smcc.starcos; + +import at.gv.egiz.smcc.CardEmul; +import javax.smartcardio.ATR; + +import at.gv.egiz.smcc.PIN; + +@SuppressWarnings("restriction") +public class STARCOSG3CardEmul extends CardEmul { + +  public static byte[] TRANSPORT_SS_PIN = new byte[] { (byte) 0x26, (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; +  public static byte[] TRANSPORT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x12, (byte) 0x34, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + +  public static byte[] DEFAULT_SS_PIN = TRANSPORT_SS_PIN; +  public static byte[] DEFAULT_Glob_PIN = new byte[] { (byte) 0x24, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; + +  protected static ATR ATR = new ATR(new byte[] { +      (byte) 0x3b, (byte) 0xbd, (byte) 0x18, (byte) 0x00, (byte) 0x81, (byte) 0x31, (byte) 0xfe, (byte) 0x45, +      (byte) 0x80, (byte) 0x51, (byte) 0x02, (byte) 0x67, (byte) 0x05, (byte) 0x18, (byte) 0xb1, (byte) 0x02, +      (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x81, (byte) 0x05, (byte) 0x31 +  }); + +  public STARCOSG3CardEmul(byte[] SS_PIN, byte[] Glob_PIN, int PIN_STATE){ +    channel = new STARCOSG3CardChannelEmul(this, Glob_PIN, PIN_STATE); +    applications.add(new STARCOSApplSichereSignatur((STARCOSCardChannelEmul) channel, +            SS_PIN, PIN_STATE)); +    applications.add(new STARCOSApplInfobox((STARCOSCardChannelEmul) channel)); +    applications.add(new STARCOSApplGewoehnlicheSignatur((STARCOSCardChannelEmul) channel, +            STARCOSApplGewoehnlicheSignatur.DST_G3)); +  } + + +  public STARCOSG3CardEmul() { +    this(DEFAULT_SS_PIN, DEFAULT_Glob_PIN, PIN.STATE_RESET); +  } + +  @Override +  public ATR getATR() { +    return ATR; +  } +} diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java new file mode 100644 index 00000000..06744c82 --- /dev/null +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSG3CardTest.java @@ -0,0 +1,119 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.smcc.starcos; + +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + + +import org.junit.Test; + +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.CardEmul; +import at.gv.egiz.smcc.CardNotSupportedException; +import at.gv.egiz.smcc.CardTerminalEmul; +import at.gv.egiz.smcc.CardTest; +import at.gv.egiz.smcc.pin.gui.ChangePINProvider; +import at.gv.egiz.smcc.LockedException; +import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.PIN; +import at.gv.egiz.smcc.PINFormatException; +import at.gv.egiz.smcc.PINMgmtSignatureCard; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.SignatureCardFactory; +import at.gv.egiz.smcc.pin.gui.SMCCTestPINProvider; +import org.junit.Ignore; + +public class STARCOSG3CardTest extends CardTest { + +  @Override +  protected SignatureCard createSignatureCard() +      throws CardNotSupportedException { +    SignatureCardFactory factory = SignatureCardFactory.getInstance(); +    STARCOSG3CardEmul card = new STARCOSG3CardEmul(); +    SignatureCard signatureCard = factory.createSignatureCard(card, +        new CardTerminalEmul(card)); +    assertTrue(signatureCard instanceof PINMgmtSignatureCard); +    return signatureCard; +  } + +  protected SignatureCard createSignatureCard(byte[] SS_PIN, byte[] Glob_PIN, int pinState) +      throws CardNotSupportedException { +    SignatureCardFactory factory = SignatureCardFactory.getInstance(); +    STARCOSG3CardEmul card = new STARCOSG3CardEmul(SS_PIN, Glob_PIN, pinState); +    SignatureCard signatureCard = factory.createSignatureCard(card, +        new CardTerminalEmul(card)); +    assertTrue(signatureCard instanceof PINMgmtSignatureCard); +    return signatureCard; +  } + +  @Test +  public void testChangePin() throws CardNotSupportedException, +      LockedException, NotActivatedException, CancelledException, +      PINFormatException, SignatureCardException, InterruptedException { + +    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( +            STARCOSG3CardEmul.DEFAULT_SS_PIN, STARCOSG3CardEmul.DEFAULT_SS_PIN, PIN.STATE_RESET); +     +    for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + +      char[] pin = "123456".toCharArray(); + +      for (int i = pinSpec.getMinLength(); i <= pinSpec.getMaxLength(); i++) { +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +        char[] newPin = new char[i]; +        Arrays.fill(newPin, '0'); +        signatureCard +            .changePIN(pinSpec, new ChangePINProvider(pin, newPin)); +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(newPin)); +        pin = newPin; +      } +    } +  } + +  @Test +  @Override +  public void testActivatePin() throws CardNotSupportedException, +      LockedException, NotActivatedException, CancelledException, +      PINFormatException, SignatureCardException, InterruptedException { + +    PINMgmtSignatureCard signatureCard = (PINMgmtSignatureCard) createSignatureCard( +            STARCOSG3CardEmul.TRANSPORT_SS_PIN, STARCOSG3CardEmul.TRANSPORT_SS_PIN, PIN.STATE_PIN_NOTACTIVE); +     +    for (PINSpec pinSpec : signatureCard.getPINSpecs()) { + +      char[] pin = "123456789".substring(0, pinSpec.getMinLength()).toCharArray(); +      char[] transportPIN = "123456".toCharArray(); + +      boolean notActive = false; +      try { +        signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +      } catch (NotActivatedException ex) { +        notActive = true; +      } +      assertTrue(notActive); + +      signatureCard.activatePIN(pinSpec, new ChangePINProvider(transportPIN, pin)); +      signatureCard.verifyPIN(pinSpec, new SMCCTestPINProvider(pin)); +    } +  } + +   +} | 
