diff options
5 files changed, 115 insertions, 47 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 6d96599c..13c57686 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -30,6 +30,8 @@ package at.gv.egiz.smcc;  import java.nio.charset.Charset; +import java.util.logging.Level; +import java.util.logging.Logger;  import javax.smartcardio.CardChannel;  import javax.smartcardio.CardException;  import javax.smartcardio.CommandAPDU; @@ -320,7 +322,12 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {    }    @Override -  protected int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException { +  public byte[] getKIDs() { +    return new byte[] { KID_PIN_DEC, KID_PIN_INF, KID_PIN_SIG }; +  } + +  @Override +  public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException {      CardChannel channel = getCardChannel(); @@ -329,8 +336,13 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {      System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length,          encodedPIN.length)); -    ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, -        kid, encodedPIN), false); +    ResponseAPDU resp; +    try { +      resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodedPIN), false); +    } catch (CardException ex) { +      log.error("smart card communication failed: " + ex.getMessage()); +      throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); +    }      if (resp.getSW() == 0x63c0) {        throw new LockedException("PIN locked."); 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 633cc90d..67f090a5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -112,7 +112,8 @@ public abstract class AbstractSignatureCard implements SignatureCard {    protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException,        SignatureCardException; -  protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException; +  // made public +//  protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException;    protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { 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 2a6e90bf..e80c6683 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -29,8 +29,10 @@  package at.gv.egiz.smcc;  import java.math.BigInteger; +import java.util.ArrayList;  import java.util.Arrays; +import java.util.List;  import javax.smartcardio.CardChannel;  import javax.smartcardio.CardException;  import javax.smartcardio.CommandAPDU; @@ -453,6 +455,11 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard      }    } +  @Override +  public byte[] getKIDs() { +    return new byte[] { KID_PIN_CARD, KID_PIN_SS }; +  } +    /**     * VERIFY PIN     * <p> @@ -466,61 +473,81 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard     *          the KID of the PIN to be verified     *      * @return -1 if VERIFY PIN was successful, or the number of possible retries  -   *  -   * @throws CardException -   *           if communication with the smart card fails. +   * +   * @throws LockedException +   *            if the pin is locked     * @throws NotActivatedException     *           if the card application has not been activated     * @throws SignatureCardException -   *           if VERIFY PIN fails +   *           if VERIFY PIN fails for some other reason (card communication error)     */    @Override -  protected int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException { -     -    CardChannel channel = getCardChannel(); +  public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { +    try { +      CardChannel channel = getCardChannel(); -    ResponseAPDU resp; -    if (pin == null) { -      resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid)); -    } else { -      // PIN length in bytes -      int len = (int) Math.ceil(pin.length() / 2); - -      // BCD encode PIN and marshal PIN block -      byte[] pinBytes = new BigInteger(pin, 16).toByteArray(); -      byte[] pinBlock = new byte[8]; -      if (len < pinBytes.length) { -        System.arraycopy(pinBytes, pinBytes.length - len, pinBlock, 1, len); +      ResponseAPDU resp; +      if (pin == null) { +        resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid));        } else { -        System.arraycopy(pinBytes, 0, pinBlock, len - pinBytes.length + 1, -            pinBytes.length); +        // PIN length in bytes +        int len = (int) Math.ceil(pin.length() / 2); + +        // BCD encode PIN and marshal PIN block +        byte[] pinBytes = new BigInteger(pin, 16).toByteArray(); +        byte[] pinBlock = new byte[8]; +        if (len < pinBytes.length) { +          System.arraycopy(pinBytes, pinBytes.length - len, pinBlock, 1, len); +        } else { +          System.arraycopy(pinBytes, 0, pinBlock, len - pinBytes.length + 1, +              pinBytes.length); +        } +        pinBlock[0] = (byte) (0x20 + len * 2); +        Arrays.fill(pinBlock, len + 1, 8, (byte) 0xff); + +        resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false); +        } -      pinBlock[0] = (byte) (0x20 + len * 2); -      Arrays.fill(pinBlock, len + 1, 8, (byte) 0xff); -      resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false); -       +      if (resp.getSW() == 0x63c0) { +        throw new LockedException("PIN locked."); +      } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { +        // return number of possible retries +        return resp.getSW2() & 0x0f; +      } else if (resp.getSW() == 0x6983) { +        throw new LockedException(); +      } else if (resp.getSW() == 0x6984) { +        // PIN LCS = "Initialized" (-> not activated) +        throw new NotActivatedException("PIN not set."); +      } else if (resp.getSW() == 0x9000) { +        return -1; // success +      } else { +        throw new SignatureCardException("Failed to verify pin: SW=" +            + Integer.toHexString(resp.getSW())); +      } +    } catch (CardException ex) { +      log.error("smart card communication failed: " + ex.getMessage()); +      throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex);      } +  } -    if (resp.getSW() == 0x63c0) { -      throw new LockedException("PIN locked."); -    } else if (resp.getSW1() == 0x63 && resp.getSW2() >> 4 == 0xc) { -      // return number of possible retries -      return resp.getSW2() & 0x0f; -    } else if (resp.getSW() == 0x6983) { -      throw new LockedException(); -    } else if (resp.getSW() == 0x6984) { -      // PIN LCS = "Initialized" (-> not activated) -      throw new NotActivatedException("PIN not set."); -    } else if (resp.getSW() == 0x9000) { -      return -1; // success -    } else { -      throw new SignatureCardException("Failed to verify pin: SW=" -          + Integer.toHexString(resp.getSW())); +  @Override +  public void reset() throws SignatureCardException { +    try { +      super.reset(); +      log.debug("select MF (e-card workaround)"); +      CardChannel channel = getCardChannel(); +      ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x00, 0x0C)); +      if (resp.getSW() != 0x9000) { +        throw new SignatureCardException("Failed to select MF after RESET: SW=" + Integer.toHexString(resp.getSW()) + "."); +      } +    } catch (CardException ex) { +      log.error("Failed to select MF after RESET: " + ex.getMessage(), ex); +      throw new SignatureCardException("Failed to select MF after RESET");      } -        } -   + +    public String toString() {      return "e-card";    } 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 439be034..bad7ccf6 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -389,4 +389,14 @@ public class SWCard implements SignatureCard {    public void reset() throws SignatureCardException {    } +  @Override +  public byte[] getKIDs() { +    return null; +  } + +  @Override +  public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { +    return -1; +  } +  } 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 d7e76dd8..1ec35b78 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -28,6 +28,7 @@  //  package at.gv.egiz.smcc; +import java.util.List;  import java.util.Locale;  import javax.smartcardio.Card; @@ -115,7 +116,24 @@ public interface SignatureCard {     */    public byte[] createSignature(byte[] hash, KeyboxName keyboxName,        PINProvider provider) throws SignatureCardException, InterruptedException; -   + +  /** +   * get the KIDs for the availabel PINs +   * @return array of KIDs +   */ +  public byte[] getKIDs(); + +  /** +   * +   * @param pin may be null to test the PIN status +   * @param kid +   * @return the number of remaining retries or -1 +   * @throws at.gv.egiz.smcc.LockedException +   * @throws at.gv.egiz.smcc.NotActivatedException +   * @throws at.gv.egiz.smcc.SignatureCardException +   */ +  public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException; +    /**     * Sets the local for evtl. required callbacks (e.g. PINSpec)     * @param locale must not be null; | 
