diff options
Diffstat (limited to 'smcc/src/main/java/at')
5 files changed, 172 insertions, 32 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 86223854..57925240 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -28,6 +28,7 @@  //  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.util.SMCCHelper;  import java.nio.charset.Charset;  import javax.smartcardio.CardChannel; @@ -104,9 +105,12 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {    public ACOSCard() {      super("at/gv/egiz/smcc/ACOSCard"); -    pinSpecs.add(PINSPEC_INF, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name"), KID_PIN_INF, null)); -    pinSpecs.add(PINSPEC_DEC, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name"), KID_PIN_DEC, null)); -    pinSpecs.add(PINSPEC_SIG, new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SIG, null)); +    pinSpecs.add(PINSPEC_INF, +            new PINSpec(0, 8, "[0-9]", getResourceBundle().getString("inf.pin.name"), KID_PIN_INF, AID_DEC)); +    pinSpecs.add(PINSPEC_DEC,  +            new PINSpec(0, 8, "[0-9]", getResourceBundle().getString("dec.pin.name"), KID_PIN_DEC, AID_DEC)); +    pinSpecs.add(PINSPEC_SIG,  +            new PINSpec(0, 8, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SIG, AID_SIG));    }    /* (non-Javadoc) @@ -334,14 +338,13 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {      CardChannel channel = getCardChannel(); -    byte[] asciiPIN = pin.getBytes(Charset.forName("ASCII")); -    byte[] encodedPIN = new byte[8]; -    System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, -        encodedPIN.length)); -      ResponseAPDU resp;      try { -      resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodedPIN), false); +      if (pin != null) { +        resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, encodePINBlock(pin)), false); +      } else { +        resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid), false); +      }      } catch (CardException ex) {        log.error("smart card communication failed: " + ex.getMessage());        throw new SignatureCardException("smart card communication failed: " + ex.getMessage(), ex); @@ -419,7 +422,28 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {      }    } +  @Override    public String toString() {      return "a-sign premium";    } + +  /** +   * ASCII encoded pin, padded with 0x00 +   * @param pin +   * @return a 8 byte pin block  +   */ +  @Override +  public byte[] encodePINBlock(String pin) { +    byte[] asciiPIN = pin.getBytes(Charset.forName("ASCII")); +    byte[] encodedPIN = new byte[8]; +    System.arraycopy(asciiPIN, 0, encodedPIN, 0, Math.min(asciiPIN.length, +        encodedPIN.length)); +//    System.out.println("ASCII encoded PIN block: " + SMCCHelper.toString(encodedPIN)); +    return encodedPIN; +  } + +  @Override +  public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { +    throw new SignatureCardException("PIN activation not supported by this card"); +  }  } 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 cb068725..63301bd1 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -28,14 +28,13 @@  //  package at.gv.egiz.smcc; +import at.gv.egiz.smcc.util.SMCCHelper;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.nio.ByteBuffer;  import java.util.ArrayList; -import java.util.HashMap;  import java.util.List;  import java.util.Locale; -import java.util.Map;  import java.util.ResourceBundle;  import javax.smartcardio.ATR; @@ -443,4 +442,54 @@ public abstract class AbstractSignatureCard implements SignatureCard {    public List<PINSpec> getPINSpecs() {      return pinSpecs;    } + +  public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { +    Card icc = getCard(); +    try { +      icc.beginExclusive(); +      CardChannel channel = icc.getBasicChannel(); + +      if (contextAID != null) { +        ResponseAPDU responseAPDU = transmit(channel, +                new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); +        if (responseAPDU.getSW() != 0x9000) { +          icc.endExclusive(); +          String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + +                  ": Failed to select AID " + SMCCHelper.toString(contextAID) + +                  ": " + SMCCHelper.toString(responseAPDU.getBytes()); +          log.error(msg); +          throw new SignatureCardException(msg); +        } +      } + +      byte[] cmd = new byte[16]; +      System.arraycopy(encodePINBlock(oldPIN), 0, cmd, 0, 8); +      System.arraycopy(encodePINBlock(newPIN), 0, cmd, 8, 8); + +      ResponseAPDU responseAPDU = transmit(channel, +              new CommandAPDU(0x00, 0x24, 0x00, kid, cmd), false); + +      icc.endExclusive(); + +      if (responseAPDU.getSW1() == 0x63 && responseAPDU.getSW2() >> 4 == 0xc) { +        int retries = responseAPDU.getSW2() & 0x0f; +        log.error("Failed VERIFY PIN, " + retries + " tries left"); +        throw new VerificationFailedException(retries); +      } +      if (responseAPDU.getSW() != 0x9000) { +        String msg = "Failed to change PIN " +                + SMCCHelper.toString(new byte[]{kid}) + ": " +                + SMCCHelper.toString(responseAPDU.getBytes()); +        log.error(msg); +        throw new SignatureCardException(msg); +      } + +    } catch (CardException ex) { +      log.error("Failed to change PIN: " + ex.getMessage()); +      throw new SignatureCardException(ex.getMessage(), ex); +    } +  } +   +  abstract byte[] encodePINBlock(String pin); +  } 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 ae43629e..b1288f74 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -28,9 +28,9 @@  //  package at.gv.egiz.smcc; -import java.math.BigInteger; +import at.gv.egiz.smcc.util.SMCCHelper;  import java.util.Arrays; - +import javax.smartcardio.Card;  import javax.smartcardio.CardChannel;  import javax.smartcardio.CardException;  import javax.smartcardio.CommandAPDU; @@ -162,8 +162,14 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard     */    public STARCOSCard() {      super("at/gv/egiz/smcc/STARCOSCard"); -    pinSpecs.add(PINSPEC_CARD, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name"), KID_PIN_CARD, null)); -    pinSpecs.add(PINSPEC_SS, new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SS, AID_DF_SS)); +    pinSpecs.add(PINSPEC_CARD,  +            new PINSpec(4, 12, "[0-9]", +              getResourceBundle().getString("card.pin.name"), +              KID_PIN_CARD, null)); +    pinSpecs.add(PINSPEC_SS, +            new PINSpec(6, 12, "[0-9]", +              getResourceBundle().getString("sig.pin.name"), +              KID_PIN_SS, AID_DF_SS));    }    @Override @@ -491,21 +497,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard        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); -        } 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); - +        byte[] pinBlock = encodePINBlock(pin);          resp = transmit(channel, new CommandAPDU(0x00, 0x20, 0x00, kid, pinBlock), false);        } @@ -553,6 +546,65 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard      return "e-card";    } -  +  /** +   * BCD encodes the pin, pads with 0xFF and prepends the pins length +   * @param pin +   * @return a 8 byte pin block consisting of length byte (0x2X), +   * the BCD encoded pin and a 0xFF padding +   */ +  @Override +  public byte[] encodePINBlock(String pin) { +    char[] pinChars = pin.toCharArray(); +    int numDigits = pinChars.length; +    int numBytes = (int) Math.ceil(numDigits/2.0); + +    byte[] pinBlock = new byte[8]; +    pinBlock[0] = (byte) (0x20 | numDigits); + +    for (int i = 0; i < numBytes; i++) { +      int p1 = 16*Character.digit(pinChars[i*2], 16); +      int p2 = (i*2+1 < numDigits) ? Character.digit(pinChars[i*2+1], 16) : 0xf; +      pinBlock[i+1] = (byte) (p1 + p2); +    } +    Arrays.fill(pinBlock, numBytes + 1, pinBlock.length, (byte) 0xff); +//    log.trace("BCD encoded PIN block: " + SMCCHelper.toString(pinBlock)); + +    return pinBlock; +  } + +  public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { +    Card icc = getCard(); +    try { +      icc.beginExclusive(); +      CardChannel channel = icc.getBasicChannel(); + +      if (contextAID != null) { +        ResponseAPDU responseAPDU = transmit(channel, +                new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); +        if (responseAPDU.getSW() != 0x9000) { +          icc.endExclusive(); +          String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + +                  ": Failed to select AID " + SMCCHelper.toString(contextAID) + +                  ": " + SMCCHelper.toString(responseAPDU.getBytes()); +          log.error(msg); +          throw new SignatureCardException(msg); +        } +      } + +      ResponseAPDU responseAPDU = transmit(channel, +              new CommandAPDU(0x00, 0x24, 0x01, kid, encodePINBlock(pin)), false); + +      icc.endExclusive(); + +      if (responseAPDU.getSW() != 0x9000) { +        String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); +        log.error(msg); +        throw new SignatureCardException(msg); +      } +    } catch (CardException ex) { +      log.error("Failed to activate PIN: " + ex.getMessage()); +      throw new SignatureCardException(ex.getMessage(), ex); +    } +  }  } 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 8dc4ac2a..57aeb994 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -403,4 +403,12 @@ public class SWCard implements SignatureCard {      return new ArrayList<PINSpec>();    } +  @Override +  public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { +  } + +  @Override +  public void activatePIN(byte kid, byte[] contextAID, String pin) throws SignatureCardException { +  } +  } 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 1e5e09c8..a88593bc 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -31,7 +31,6 @@ package at.gv.egiz.smcc;  import java.util.List;  import java.util.Locale; -import java.util.Map;  import javax.smartcardio.Card;  import javax.smartcardio.CardTerminal; @@ -135,11 +134,19 @@ public interface SignatureCard {     */    public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException; +  public void changePIN(byte kid, byte[] contextAID, +          String oldPIN, String newPIN) +          throws SignatureCardException, VerificationFailedException; + +  public void activatePIN(byte kid, byte[] contextAID, +          String pin) +          throws SignatureCardException; +    /**     * Sets the local for evtl. required callbacks (e.g. PINSpec)     * @param locale must not be null;     */    public void setLocale(Locale locale); - +    } | 
