diff options
Diffstat (limited to 'smcc')
13 files changed, 963 insertions, 182 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 414d4678..a63d4076 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -16,9 +16,13 @@  */  package at.gv.egiz.smcc; +import java.io.ByteArrayOutputStream;  import java.io.IOException; +import java.io.InputStream;  import java.security.AlgorithmParameters;  import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException;  import java.util.Arrays;  import java.util.List; @@ -375,12 +379,46 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC    @Override    @Exclusive -  public byte[] createSignature(byte[] hash, KeyboxName keyboxName, -      PINProvider provider) throws SignatureCardException, InterruptedException { +  public byte[] createSignature(InputStream input, KeyboxName keyboxName, +      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { -    if (hash.length != 20) { -      throw new IllegalArgumentException("Hash value must be of length 20."); +    ByteArrayOutputStream dst = new ByteArrayOutputStream(); +    // key ID +    dst.write(new byte[]{(byte) 0x84, (byte) 0x01, (byte) 0x88}); +    // algorithm ID +    dst.write(new byte[]{(byte) 0x80, (byte) 0x01}); +     +    MessageDigest md; +    try { +      if ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1".equals(alg)) { +        dst.write((byte) 0x14); // SHA-1/ECC +        md = MessageDigest.getInstance("SHA-1"); +      } else if ("http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { +        dst.write((byte) 0x12); // SHA-1 with padding according to PKCS#1 block type 01 +        md = MessageDigest.getInstance("SHA-1"); +      } else if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName) +          && appVersion >= 2 +          && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256".equals(alg)) { +        dst.write((byte) 0x44); // SHA-256/ECC +        md = MessageDigest.getInstance("SHA256"); +      } else if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName) +          && appVersion >= 2 +          && "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256".equals(alg)) { +        dst.write((byte) 0x41); // SHA-256 with padding according to PKCS#1 +        md = MessageDigest.getInstance("SHA256"); +      } else { +        throw new SignatureCardException("Card does not support signature algorithm " + alg + "."); +      } +    } catch (NoSuchAlgorithmException e) { +      log.error("Failed to get MessageDigest.", e); +      throw new SignatureCardException(e);      } +     +    byte[] digest = new byte[md.getDigestLength()]; +    for (int l; (l = input.read(digest)) != -1;) { +      md.update(digest, 0, l); +    } +    digest = md.digest();      try { @@ -393,11 +431,11 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC          // SELECT application          execSELECT_AID(channel, AID_SIG);          // MANAGE SECURITY ENVIRONMENT : SET DST -        execMSE(channel, 0x41, 0xb6, DST_SIG); +        execMSE(channel, 0x41, 0xb6, dst.toByteArray());          // VERIFY          verifyPINLoop(channel, spec, provider);          // PERFORM SECURITY OPERATION : HASH -        execPSO_HASH(channel, hash); +        execPSO_HASH(channel, digest);          // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATRE          return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); @@ -413,7 +451,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC          while (true) {            try {              // INTERNAL AUTHENTICATE -            return execINTERNAL_AUTHENTICATE(channel, hash); +            return execINTERNAL_AUTHENTICATE(channel, digest);            } catch (SecurityStatusNotSatisfiedException e) {              verifyPINLoop(channel, spec, provider);            } @@ -711,6 +749,9 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC      ResponseAPDU resp = channel.transmit(          new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); +    if (resp.getSW() == 0x6982) { +      throw new SecurityStatusNotSatisfiedException(); +    }      if (resp.getSW() != 0x9000) {        throw new SignatureCardException(            "PSO - COMPUTE DIGITAL SIGNATRE failed: SW=" diff --git a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java new file mode 100644 index 00000000..15b47fb0 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java @@ -0,0 +1,283 @@ +/* +* 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; + +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.util.ISO7816Utils; +import at.gv.egiz.smcc.util.SMCCHelper; + +public class BELPICCard extends AbstractSignatureCard implements SignatureCard { +   +    /** +     * Logging facility. +     */ +    private static Log log = LogFactory.getLog(BELPICCard.class); + +    public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; + +    public static final byte[] DF_BELPIC = new byte[] { (byte) 0xDF, +            (byte) 0x00 }; + +    public static final byte[] DF_ID = new byte[] { (byte) 0xDF, (byte) 0x01 }; + +    public static final byte[] SIGN_CERT = new byte[] { (byte) 0x50, +            (byte) 0x39 }; + +//    public static final byte MSE_SET_ALGO_REF = (byte) 0x02; + +//    public static final byte MSE_SET_PRIV_KEY_REF = (byte) 0x83; + +    public static final int SIGNATURE_LENGTH = (int) 0x80; + +    public static final byte KID = (byte) 0x01; + +    public static final int READ_BUFFER_LENGTH = 256; + +    public static final int PINSPEC_SS = 0; +     +  private static final PINSpec SS_PIN_SPEC =  +    new PINSpec(4, 12, "[0-9]", +      "at/gv/egiz/smcc/BelpicCard", "sig.pin", KID, DF_BELPIC); +     +  /** +   * Creates a new instance. +   */ +  public BELPICCard() { +    super("at/gv/egiz/smcc/BelpicCard"); +    pinSpecs.add(SS_PIN_SPEC); +  } + +  @Override +  @Exclusive +  public byte[] getCertificate(KeyboxName keyboxName) +      throws SignatureCardException { + +    if (keyboxName != KeyboxName.SECURE_SIGNATURE_KEYPAIR) { +      throw new IllegalArgumentException("Keybox " + keyboxName +          + " not supported"); +    } + +    try { +      CardChannel channel = getCardChannel(); +      // SELECT MF +      execSELECT_FID(channel, MF); +      // SELECT application +      execSELECT_FID(channel, DF_BELPIC); +      // SELECT file +      execSELECT_FID(channel, SIGN_CERT); +      // READ BINARY +      byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, -1, (byte) 0x30); +      if (certificate == null) { +        throw new NotActivatedException(); +      } +      return certificate; +    } catch (FileNotFoundException e) { +      throw new NotActivatedException(); +    } catch (CardException e) { +      log.info("Failed to get certificate.", e); +      throw new SignatureCardException(e); +    } + +  } + +  @Override +  @Exclusive +  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +      throws SignatureCardException, InterruptedException { +       +    throw new IllegalArgumentException("Infobox '" + infobox +        + "' not supported."); +  } + +  @Override +  @Exclusive +  public byte[] createSignature(InputStream input, KeyboxName keyboxName, +      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { +     +    if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { +      throw new SignatureCardException("Card does not support key " + keyboxName + "."); +    } +    if (!"http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { +      throw new SignatureCardException("Card does not support algorithm " + alg + "."); +    } +     +    byte[] dst = new byte[] { (byte) 0x04, // number of following +        // bytes +        (byte) 0x80, // tag for algorithm reference +        (byte) 0x02, // algorithm reference +        (byte) 0x84, // tag for private key reference +        (byte) 0x83 // private key reference +    }; +     +    MessageDigest md; +    try { +      md = MessageDigest.getInstance("SHA-1"); +    } catch (NoSuchAlgorithmException e) { +      log.error("Failed to get MessageDigest.", e); +      throw new SignatureCardException(e); +    } +    // calculate message digest +    byte[] digest = new byte[md.getDigestLength()]; +    for (int l; (l = input.read(digest)) != -1;) { +      md.update(digest, 0, l); +    } +    digest = md.digest(); + +    try { +       +      CardChannel channel = getCardChannel(); + +      // SELECT MF +      execSELECT_FID(channel, MF); +      // VERIFY +      execMSE(channel, 0x41, 0xb6, dst); +      // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE +      verifyPINLoop(channel, SS_PIN_SPEC, provider); +      // MANAGE SECURITY ENVIRONMENT : SET DST +      return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); + +    } catch (CardException e) { +      log.warn(e); +      throw new SignatureCardException("Failed to access card.", e); +    } + +  } + +  public String toString() { +    return "Belpic Card"; +  } +   +  protected void verifyPINLoop(CardChannel channel, PINSpec spec, +      PINProvider provider) throws LockedException, NotActivatedException, +      SignatureCardException, InterruptedException, CardException { +     +    int retries = -1; //verifyPIN(channel, spec, null, -1); +    do { +      retries = verifyPIN(channel, spec, provider, retries); +    } while (retries > 0); +  } + +  protected int verifyPIN(CardChannel channel, PINSpec pinSpec, +      PINProvider provider, int retries) throws SignatureCardException, +      LockedException, NotActivatedException, InterruptedException, +      CardException { +     +    VerifyAPDUSpec apduSpec = new VerifyAPDUSpec( +        new byte[] { +            (byte) 0x00, (byte) 0x20, (byte) 0x00, 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); +     +    ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +     +    if (resp.getSW() == 0x9000) { +      return -1; +    } +    if (resp.getSW() >> 4 == 0x63c) { +      return 0x0f & resp.getSW(); +    } +     +    switch (resp.getSW()) { +    case 0x6983: +      // authentication method blocked +      throw new LockedException(); +    case 0x6984: +      // reference data not usable +      throw new NotActivatedException(); +    case 0x6985: +      // conditions of use not satisfied +      throw new NotActivatedException(); +   +    default: +      String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW());  +      log.info(msg); +      throw new SignatureCardException(msg); +    } +     +  } +   +  protected byte[] execSELECT_FID(CardChannel channel, byte[] fid) +      throws SignatureCardException, CardException { +     +    ResponseAPDU resp = channel.transmit( +        new CommandAPDU(0x00, 0xA4, 0x02, 0x0C, fid, 256)); +     +    if (resp.getSW() == 0x6A82) { +      String msg = "File or application not found FID=" +          + SMCCHelper.toString(fid) + " SW=" +          + Integer.toHexString(resp.getSW()) + "."; +      log.info(msg); +      throw new FileNotFoundException(msg); +    } else if (resp.getSW() != 0x9000) { +      String msg = "Failed to select application FID=" +          + SMCCHelper.toString(fid) + " SW=" +          + Integer.toHexString(resp.getSW()) + "."; +      log.error(msg); +      throw new SignatureCardException(msg); +    } else { +      return resp.getBytes(); +    } +     +  } +   +  protected void execMSE(CardChannel channel, int p1, int p2, byte[] data) +      throws CardException, SignatureCardException { +    ResponseAPDU resp = channel.transmit( +        new CommandAPDU(0x00, 0x22, p1, p2, data, 256)); +    if (resp.getSW() != 0x9000) { +      throw new SignatureCardException("MSE:SET failed: SW=" +          + Integer.toHexString(resp.getSW())); +    } +  } + +  protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, byte[] hash) +      throws CardException, SignatureCardException { +    ResponseAPDU resp; +    resp = channel.transmit( +        new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, hash, 256)); +    if (resp.getSW() == 0x6982) { +      throw new SecurityStatusNotSatisfiedException(); +    } else if (resp.getSW() == 0x6983) { +      throw new LockedException(); +    } else if (resp.getSW() != 0x9000) { +      throw new SignatureCardException( +          "PSO: COMPUTE DIGITAL SIGNATRE failed: SW=" +              + Integer.toHexString(resp.getSW())); +    } else { +      return resp.getData(); +    } +  } + + + +     +}
\ No newline at end of file diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java new file mode 100644 index 00000000..831a1f9b --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java @@ -0,0 +1,297 @@ +/* +* 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; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.util.ISO7816Utils; +import at.gv.egiz.smcc.util.SMCCHelper; + +public class ITCard extends AbstractSignatureCard { +   +  /** +   * Logging facility. +   */ +  private static Log log = LogFactory.getLog(STARCOSCard.class); +   +  public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; +   +  public static final byte[] DF1 = new byte[] { (byte) 0x11, (byte) 0x00 }; +   +  public static final byte[] EF_C_Carta = new byte[] { (byte) 0x11, (byte) 0x01 }; +   +  private static final PINSpec SS_PIN_SPEC =  +    new PINSpec(5, 8, "[0-9]",  +        "at/gv/egiz/smcc/ITCard", "sig.pin", (byte) 0x10,  +        new byte[] { (byte) 0x11, (byte) 0x00 }); + +  /** +   * Creates a new instance. +   */ +  public ITCard() { +    super("at/gv/egiz/smcc/ITCard"); +    pinSpecs.add(SS_PIN_SPEC); +  } + +  @Override +  @Exclusive +  public byte[] getCertificate(KeyboxName keyboxName) +      throws SignatureCardException, InterruptedException { + +    if (keyboxName != KeyboxName.SECURE_SIGNATURE_KEYPAIR) { +      throw new IllegalArgumentException("Keybox " + keyboxName +          + " not supported"); +    } + +    try { +      CardChannel channel = getCardChannel(); +      // SELECT MF +      execSELECT_FID(channel, MF); +      // SELECT application +      execSELECT_FID(channel, DF1); +      // SELECT EF_C_Carta +      byte[] fcx = execSELECT_FID(channel, EF_C_Carta); +      int maxsize = ISO7816Utils.getLengthFromFCx(fcx); +      // READ BINARY +      byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, maxsize, (byte) 0x30); +      if (certificate == null) { +        throw new NotActivatedException(); +      } +      return certificate; +    } catch (FileNotFoundException e) { +      throw new NotActivatedException(); +    } catch (CardException e) { +      log.info("Failed to get certificate.", e); +      throw new SignatureCardException(e); +    } +     +  } + +  @Override +  @Exclusive +  public byte[] getInfobox(String infobox, PINProvider provider, String domainId) +      throws SignatureCardException, InterruptedException { +       +    throw new IllegalArgumentException("Infobox '" + infobox +        + "' not supported."); +  } + +  @Override +  @Exclusive +  public byte[] createSignature(InputStream input, KeyboxName keyboxName, +      PINProvider provider, String alg) throws SignatureCardException, +      InterruptedException, IOException { + +    if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { +      throw new SignatureCardException("Card does not support key " + keyboxName + "."); +    } +    if (!"http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { +      throw new SignatureCardException("Card does not support algorithm " + alg + "."); +    } + +    byte[] dst = new byte[] { +        (byte) 0x83, // tag for algorithm reference +        (byte) 0x01, // algorithm reference +        (byte) 0x01  // private key reference +    }; +     +    MessageDigest md; +    try { +      md = MessageDigest.getInstance("SHA-1"); +    } catch (NoSuchAlgorithmException e) { +      log.error("Failed to get MessageDigest.", e); +      throw new SignatureCardException(e); +    } +    // calculate message digest +    byte[] digest = new byte[md.getDigestLength()]; +    for (int l; (l = input.read(digest)) != -1;) { +      md.update(digest, 0, l); +    } +    digest = md.digest(); + +    try { +       +      CardChannel channel = getCardChannel(); + +      // SELECT MF +      execSELECT_FID(channel, MF); +      // VERIFY +      verifyPINLoop(channel, SS_PIN_SPEC, provider); +      // MANAGE SECURITY ENVIRONMENT : RESTORE SE +      execMSE(channel, 0xF3, 0x03, null); +      // MANAGE SECURITY ENVIRONMENT : SET DST +      execMSE(channel, 0xF1, 0xB8, dst); +      // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE +      return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); + +    } catch (CardException e) { +      log.warn(e); +      throw new SignatureCardException("Failed to access card.", e); +    } + +  } + +  protected void verifyPINLoop(CardChannel channel, PINSpec spec, +      PINProvider provider) throws LockedException, NotActivatedException, +      SignatureCardException, InterruptedException, CardException { +     +    int retries = -1; +    do { +      retries = verifyPIN(channel, spec, provider, retries); +    } while (retries >= -1); +  } + +  protected int verifyPIN(CardChannel channel, PINSpec pinSpec, +      PINProvider provider, int retries) throws SignatureCardException, +      LockedException, NotActivatedException, InterruptedException, +      CardException { +     +    VerifyAPDUSpec apduSpec = new VerifyAPDUSpec( +        new byte[] { +            (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID(), (byte) 0x08, +            (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +            (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff },  +        0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); +     +    ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); +     +    if (resp.getSW() == 0x9000) { +      return -2; +    } +    if (resp.getSW() >> 4 == 0x63c) { +      return 0x0f & resp.getSW(); +    } +     +    switch (resp.getSW()) { +    case 0x6300: +      // incorrect PIN, number of retries not provided +      return -1; +    case 0x6983: +      // authentication method blocked +      throw new LockedException(); +    case 0x6984: +      // reference data not usable +      throw new NotActivatedException(); +    case 0x6985: +      // conditions of use not satisfied +      throw new NotActivatedException(); +   +    default: +      String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW());  +      log.info(msg); +      throw new SignatureCardException(msg); +    } +     +  } + +  protected byte[] execSELECT_FID(CardChannel channel, byte[] fid) +      throws SignatureCardException, CardException { +     +    ResponseAPDU resp = channel.transmit( +        new CommandAPDU(0x00, 0xA4, 0x00, 0x00, fid, 256)); +     +    if (resp.getSW() == 0x6A82) { +      String msg = "File or application not found FID=" +          + SMCCHelper.toString(fid) + " SW=" +          + Integer.toHexString(resp.getSW()) + "."; +      log.info(msg); +      throw new FileNotFoundException(msg); +    } else if (resp.getSW() != 0x9000) { +      String msg = "Failed to select application FID=" +          + SMCCHelper.toString(fid) + " SW=" +          + Integer.toHexString(resp.getSW()) + "."; +      log.error(msg); +      throw new SignatureCardException(msg); +    } else { +      return resp.getBytes(); +    } +     +  } +   +  protected void execMSE(CardChannel channel, int p1, int p2, byte[] data) +      throws CardException, SignatureCardException { +     +    ResponseAPDU resp; +    if (data == null) { +      resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2)); +    } else { +      resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2, data)); +    } +     +    if (resp.getSW() != 0x9000) { +      throw new SignatureCardException("MSE:SET failed: SW=" +          + Integer.toHexString(resp.getSW())); +    } +  } + +  protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, +      byte[] hash) throws CardException, SignatureCardException { +     +    byte[] oid = new byte[] { (byte) 0x30, (byte) 0x21, (byte) 0x30, +        (byte) 0x09, (byte) 0x06, (byte) 0x05, (byte) 0x2b, +        (byte) 0x0e, (byte) 0x03, (byte) 0x02, (byte) 0x1a, +        (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x14 }; +     +    ByteArrayOutputStream data = new ByteArrayOutputStream(); +     +    try { +      // header +      data.write(new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x01 }); +      // padding +      for (int i = 0, len = 125 - hash.length - oid.length; i < len; i++) { +        data.write((byte) 0xFF); +      } +      data.write((byte) 0x00); +      // oid +      data.write(oid); +      // hash +      data.write(hash); +    } catch (IOException e) { +      throw new SignatureCardException(e); +    } +     +    ResponseAPDU resp = channel +          .transmit(new CommandAPDU(0x00, 0x2A, 0x80, 0x86, data.toByteArray(), 0x81)); + +     +    if (resp.getSW() == 0x6982) { +      throw new SecurityStatusNotSatisfiedException(); +    } else if (resp.getSW() == 0x6983) { +      throw new LockedException(); +    } else if (resp.getSW() != 0x9000) { +      throw new SignatureCardException( +          "PSO: COMPUTE DIGITAL SIGNATRE failed: SW=" +              + Integer.toHexString(resp.getSW())); +    } else { +      return resp.getData(); +    } +} + +} 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 a0c2391d..01de8a77 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -19,11 +19,16 @@ package at.gv.egiz.smcc;  import java.io.ByteArrayOutputStream;  import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException;  import java.util.Arrays;  import java.util.List; +import javax.smartcardio.Card;  import javax.smartcardio.CardChannel;  import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal;  import javax.smartcardio.CommandAPDU;  import javax.smartcardio.ResponseAPDU; @@ -41,6 +46,8 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    private static Log log = LogFactory.getLog(STARCOSCard.class);    public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; +   +  public static final byte[] EF_VERSION = new byte[] { (byte) 0x00, (byte) 0x32 };    /**     * Application ID <em>SV-Personendaten</em>. @@ -106,19 +113,6 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    public static final byte[] EF_C_X509_CA_CS_DS = new byte[] { (byte) 0xc6,        (byte) 0x08 }; -  public static final byte[] DST_SS = new byte[] { (byte) 0x84, (byte) 0x03, // tag -      // , -      // length -      // ( -      // key -      // desc -      // . -      // ) -      (byte) 0x80, (byte) 0x02, (byte) 0x00, // local, key ID, key version -      (byte) 0x89, (byte) 0x03, // tag, length (algorithm ID) -      (byte) 0x13, (byte) 0x35, (byte) 0x10 // ECDSA -  }; -    public static final byte KID_PIN_SS = (byte) 0x81;    // Gewöhnliche Signatur (GS) @@ -133,19 +127,6 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    public static final byte[] EF_C_X509_CA_CS = new byte[] { (byte) 0x2f,        (byte) 0x02 }; -  public static final byte[] DST_GS = new byte[] { (byte) 0x84, (byte) 0x03, // tag -      // , -      // length -      // ( -      // key -      // desc -      // . -      // ) -      (byte) 0x80, (byte) 0x02, (byte) 0x00, // local, key ID, key version -      (byte) 0x89, (byte) 0x03, // tag, length (algorithm ID) -      (byte) 0x13, (byte) 0x35, (byte) 0x10 // ECDSA -  }; -    public static final byte KID_PIN_CARD = (byte) 0x01;    private static final PINSpec CARD_PIN_SPEC = @@ -155,9 +136,11 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    private static final PINSpec SS_PIN_SPEC =      new PINSpec(6, 12, "[0-9]",           "at/gv/egiz/smcc/STARCOSCard", "sig.pin", KID_PIN_SS, AID_DF_SS); +   +  protected double version = 1.1;    /** -   * Creates an new instance. +   * Creates a new instance.     */    public STARCOSCard() {      super("at/gv/egiz/smcc/STARCOSCard"); @@ -165,6 +148,35 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      pinSpecs.add(SS_PIN_SPEC);    } +  /* (non-Javadoc) +   * @see at.gv.egiz.smcc.AbstractSignatureCard#init(javax.smartcardio.Card, javax.smartcardio.CardTerminal) +   */ +  @Override +  public void init(Card card, CardTerminal cardTerminal) { +    super.init(card, cardTerminal); +     +    // determine application version +    CardChannel channel = getCardChannel(); +    try { +      // SELECT MF +      execSELECT_MF(channel); +      // SELECT EF_VERSION +      execSELECT_FID(channel, EF_VERSION); +      // READ BINARY +      byte[] ver = ISO7816Utils.readRecord(channel, 1); +      if (ver[0] == (byte) 0xa5 && ver[2] == (byte) 0x53) { +        version = (0x0F & ver[4]) + (0xF0 & ver[5])/160.0 + (0x0F & ver[5])/100.0; +        String generation = (version < 1.2) ? "<= G2" : "G3"; +        log.info("e-card version=" + version + " (" + generation + ")"); +      } +    } catch (CardException e) { +      log.warn(e); +    } catch (SignatureCardException e) { +      log.warn(e); +    } +     +  } +    @Override    @Exclusive    public byte[] getCertificate(KeyboxName keyboxName) @@ -281,19 +293,57 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu    @Override    @Exclusive -  public byte[] createSignature(byte[] hash, KeyboxName keyboxName, -      PINProvider provider) throws SignatureCardException, InterruptedException { +  public byte[] createSignature(InputStream input, KeyboxName keyboxName, +      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { -    if (hash.length != 20) { -      throw new IllegalArgumentException("Hash value must be of length 20."); +    ByteArrayOutputStream dst = new ByteArrayOutputStream(); +    byte[] ht = null; +     +    MessageDigest md = null; +    try { +      if (version < 1.2 && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1".equals(alg)) { +        // local key ID '02' version '00' +        dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00}); +        // algorithm ID ECDSA with SHA-1 +        dst.write(new byte[] {(byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10}); +        md = MessageDigest.getInstance("SHA-1"); +      } else if (version >= 1.2 && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256".equals(alg)) { +        // local key ID '02' version '00' +        dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00}); +        // portable algorithm reference +        dst.write(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x04}); +        // hash template +        ht = new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x40}; +        md = MessageDigest.getInstance("SHA256"); +      } else if (version >= 1.2 && "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256".equals(alg)) { +        // local key ID '03' version '00' +        dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x03, (byte) 0x00}); +        // portable algorithm reference +        dst.write(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x02}); +        // hash template +        ht = new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x40}; +        md = MessageDigest.getInstance("SHA256"); +      } else { +        throw new SignatureCardException("e-card versio " + version + " does not support signature algorithm " + alg + "."); +      } +    } catch (NoSuchAlgorithmException e) { +      log.error("Failed to get MessageDigest.", e); +      throw new SignatureCardException(e);      } -   +     +    // calculate message digest +    byte[] digest = new byte[md.getDigestLength()]; +    for (int l; (l = input.read(digest)) != -1;) { +      md.update(digest, 0, l); +    } +    digest = md.digest(); +      try {        CardChannel channel = getCardChannel();        if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { - +                  PINSpec spec = SS_PIN_SPEC;          // SELECT MF @@ -303,11 +353,21 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu          // VERIFY          verifyPINLoop(channel, spec, provider);          // MANAGE SECURITY ENVIRONMENT : SET DST -        execMSE(channel, 0x41, 0xb6, DST_SS); -        // PERFORM SECURITY OPERATION : HASH -        execPSO_HASH(channel, hash); -        // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE -        return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); +        execMSE(channel, 0x41, 0xb6, dst.toByteArray()); +        if (ht != null) { +          // PERFORM SECURITY OPERATION : SET HT +          execMSE(channel, 0x41, 0xaa, ht); +        } +        if (version < 1.2) { +          // PERFORM SECURITY OPERATION : HASH +          execPSO_HASH(channel, digest); +          // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE +          return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, null); +        } else { +          // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE +          return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); +        } +                } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { @@ -316,14 +376,17 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu          // SELECT application          execSELECT_AID(channel, AID_DF_GS);          // MANAGE SECURITY ENVIRONMENT : SET DST -        execMSE(channel, 0x41, 0xb6, DST_GS); +        execMSE(channel, 0x41, 0xb6, dst.toByteArray()); +        if (ht != null) { +          // PERFORM SECURITY OPERATION : SET HT +          execMSE(channel, 0x41, 0xaa, ht); +        }          // PERFORM SECURITY OPERATION : HASH -        execPSO_HASH(channel, hash); -         +        execPSO_HASH(channel, digest);          while (true) {            try {              // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE -            return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); +            return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, null);            } catch (SecurityStatusNotSatisfiedException e) {              verifyPINLoop(channel, spec, provider);            } @@ -682,7 +745,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      ResponseAPDU resp = channel.transmit(          new CommandAPDU(0x00, 0x22, p1, p2, data));      if (resp.getSW() != 0x9000) { -      throw new SignatureCardException("MSE:SET DST failed: SW=" +      throw new SignatureCardException("MSE:SET failed: SW="            + Integer.toHexString(resp.getSW()));      }    } @@ -701,10 +764,47 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu      }    } -  protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel) +  protected void execPSO_HASH(CardChannel channel, InputStream input) +      throws SignatureCardException, CardException { +    ResponseAPDU resp; +    int blockSize = 64; +    byte[] b = new byte[blockSize]; +    try { +      ByteArrayOutputStream data = new ByteArrayOutputStream(); +      // initialize +      data.write((byte) 0x90); +      data.write((byte) 0x00); +      resp = channel.transmit( +          new CommandAPDU(0x10, 0x2A, 0x90, 0xA0, data.toByteArray())); +      data.reset(); +      for (int l; (l = input.read(b)) != -1;) { +        data.write((byte) 0x80); +        data.write(l); +        data.write(b, 0, l); +        resp = channel.transmit( +            new CommandAPDU((l == blockSize) ? 0x10 : 0x00, 0x2A, 0x90, 0xA0, data.toByteArray())); +        if (resp.getSW() != 0x9000) { +          throw new SignatureCardException("PSO:HASH failed: SW=" +              + Integer.toHexString(resp.getSW())); +        } +        data.reset(); +      } +    } catch (IOException e) { +      throw new SignatureCardException(e); +    } +     +  } + +  protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, byte[] hash)        throws CardException, SignatureCardException { -    ResponseAPDU resp = channel.transmit( -        new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); +    ResponseAPDU resp; +    if (hash != null) { +      resp = channel.transmit( +          new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, hash, 256)); +    } else { +      resp = channel.transmit( +          new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); +    }      if (resp.getSW() == 0x6982) {        throw new SecurityStatusNotSatisfiedException();      } else if (resp.getSW() == 0x6983) { 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 279362c0..670704d5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -20,6 +20,7 @@ import java.io.ByteArrayOutputStream;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  import java.io.IOException; +import java.io.InputStream;  import java.io.InputStreamReader;  import java.nio.charset.Charset;  import java.security.InvalidKeyException; @@ -308,7 +309,7 @@ public class SWCard implements SignatureCard {    }    @Override -  public byte[] createSignature(byte[] hash, KeyboxName keyboxName, PINProvider provider) throws SignatureCardException, InterruptedException { +  public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException {      // KeyStore password      char[] password = getPassword(keyboxName); @@ -363,7 +364,10 @@ public class SWCard implements SignatureCard {      try {        Signature signature = Signature.getInstance(algorithm);        signature.initSign(privateKey); -      signature.update(hash); +      int l; +      for (byte[] b = new byte[20]; (l = input.read(b)) != -1;) { +        signature.update(b, 0, l); +      }        return signature.sign();      } catch (NoSuchAlgorithmException e) {        String msg = "Algorithm + '" + algorithm + "' not supported for signing."; 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 1a163783..3d56f97b 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -18,6 +18,9 @@  package at.gv.egiz.smcc;  import at.gv.egiz.smcc.ccid.CCID; + +import java.io.IOException; +import java.io.InputStream;  import java.util.Locale;  import javax.smartcardio.Card; @@ -101,15 +104,17 @@ public interface SignatureCard {    /**     *  -   * @param hash +   * @param input     * @param keyboxName     * @param provider +   * @param alg TODO     * @return     * @throws at.gv.egiz.smcc.SignatureCardException     * @throws java.lang.InterruptedException if applet is destroyed while in pin dialog +   * @throws IOException      */ -  public byte[] createSignature(byte[] hash, KeyboxName keyboxName, -      PINProvider provider) throws SignatureCardException, InterruptedException; +  public byte[] createSignature(InputStream input, KeyboxName keyboxName, +      PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException;    public CCID getReader(); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java index 26844473..47053f98 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java @@ -170,21 +170,21 @@ public class SignatureCardFactory {          },          "at.gv.egiz.smcc.STARCOSCard")); -//    // e-card G3 -//    supportedCards.add(new SupportedCard( -//        // ATR  (3b:dd:96:ff:81:b1:fe:45:1f:03:80:31:b0:52:02:03:64:04:1b:b4:22:81:05:18) -//        new byte[] { -//            (byte) 0x3b, (byte) 0xdd, (byte) 0x96, (byte) 0xff, (byte) 0x81, (byte) 0xb1, (byte) 0xfe, (byte) 0x45,  -//            (byte) 0x1f, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,  -//            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 -//        }, -//        // mask ( -//        new byte[] { -//            (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,  -//            (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,  -//            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00  -//        }, -//        "at.gv.egiz.smcc.STARCOSCard")); +    // e-card G3 +    supportedCards.add(new SupportedCard( +        // ATR  (3b:dd:96:ff:81:b1:fe:45:1f:03:80:31:b0:52:02:03:64:04:1b:b4:22:81:05:18) +        new byte[] { +            (byte) 0x3b, (byte) 0xdd, (byte) 0x96, (byte) 0xff, (byte) 0x81, (byte) 0xb1, (byte) 0xfe, (byte) 0x45,  +            (byte) 0x1f, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,  +            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 +        }, +        // mask ( +        new byte[] { +            (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,  +            (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,  +            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00  +        }, +        "at.gv.egiz.smcc.STARCOSCard"));      // a-sign premium      supportedCards.add(new SupportedCard( @@ -202,6 +202,72 @@ public class SignatureCardFactory {          },          "at.gv.egiz.smcc.ACOSCard")); +    // BELPIC +    supportedCards.add(new SupportedCard( +            // ATR (3b:98:13:40:0A:A5:03:01:01:01:AD:13:11) +            new byte[] { (byte) 0x3b, (byte) 0x98, (byte) 0x13, +                    (byte) 0x40, (byte) 0x0a, (byte) 0xa5, (byte) 0x03, +                    (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0xad, +                    (byte) 0x13, (byte) 0x11 }, +            // mask (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff) +            new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, +                    (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                    (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                    (byte) 0xff, (byte) 0xff }, +            "at.gv.egiz.smcc.BELPICCard")); +     +    // ITCards +    supportedCards.add(new SupportedCard( +    // ATR = +    // [3b:ff:18:00:ff:81:31:fe:55:00:6b:02:09:02:00:01:11:01:43:4e:53:11:31:80:8e] +            new byte[] { (byte) 0x3b, (byte) 0xff, (byte) 0x18, +                    (byte) 0x00, (byte) 0xff, (byte) 0x81, (byte) 0x31, +                    (byte) 0xfe, (byte) 0x55, (byte) 0x00, (byte) 0x6b, +                    (byte) 0x02, (byte) 0x09 /* +                                             * , (byte) 0x02, (byte) 0x00, +                                             * (byte) 0x01, (byte) 0x11, +                                             * (byte) 0x01, (byte) 0x43, +                                             * (byte) 0x4e, (byte) 0x53, +                                             * (byte) 0x11, (byte) 0x31, +                                             * (byte) 0x80, (byte) 0x8e +                                             */ +            }, +            // mask (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff) +            new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, +                    (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                    (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                    (byte) 0xff, (byte) 0xff /* +                                             * , (byte) 0xff, (byte) 0xff, +                                             * (byte) 0xff, (byte) 0xff, +                                             * (byte) 0xff, (byte) 0xff, +                                             * (byte) 0xff, (byte) 0xff, +                                             * (byte) 0xff, (byte) 0xff, +                                             * (byte) 0xff, (byte) 0xff +                                             */ +            }, "at.gv.egiz.smcc.ITCard")); +    supportedCards.add(new SupportedCard( +        // ATR +        // (3B:FF:18:00:FF:C1:0A:31:FE:55:00:6B:05:08:C8:05:01:01:01:43:4E:53:10:31:80:1C) +        new byte[] { (byte) 0x3b, (byte) 0xff, (byte) 0x18, +                (byte) 0x00, (byte) 0xFF, (byte) 0xC1, (byte) 0x0a, +                (byte) 0x31, (byte) 0xfe, (byte) 0x55, (byte) 0x00, +                (byte) 0x6B, (byte) 0x05, (byte) 0x08, (byte) 0xC8, +                (byte) 0x05, (byte) 0x01, (byte) 0x01, (byte) 0x01, +                (byte) 0x43, (byte) 0x4E, (byte) 0x53, (byte) 0x10, +                (byte) 0x31, (byte) 0x80, (byte) 0x1C }, +        // mask +        // (ff:ff:ff:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00) +        new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, +                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, +                (byte) 0xff, (byte) 0xff, (byte) 0xff }, +        "at.gv.egiz.smcc.ITCard")); + +     +        }    /** diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java b/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java index c5c7cbc9..fcd0b876 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java @@ -103,6 +103,14 @@ public class ISO7816Utils {      TransparentFileInputStream is = openTransparentFileInputStream(channel,          maxSize); +     +    return readTransparentFileTLV(is, maxSize, expectedType); + +  } +   +  public static byte[] readTransparentFileTLV(TransparentFileInputStream is, int maxSize, +      byte expectedType) throws CardException, SignatureCardException { +      try { @@ -170,7 +178,8 @@ public class ISO7816Utils {        while (pos < (fcx[1] - 2)) {          switch (fcx[pos]) { -        case (byte) 0x80: { +        case (byte) 0x80:  +        case (byte) 0x81: {            len = 0xFF & fcx[pos + 2];            for (int i = 1; i < fcx[pos + 1]; i++) {              len<<=8; diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties new file mode 100644 index 00000000..71267394 --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties @@ -0,0 +1,3 @@ +#pin.name=PIN
 +sig.pin.name=PIN
 +sig.pin.length=4-12
\ No newline at end of file diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties new file mode 100644 index 00000000..e0222a70 --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties @@ -0,0 +1,3 @@ +#pin.name=PIN
 +sig.pin.name=PIN
 +sig.pin.length=5-8
\ No newline at end of file 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 2a55357d..b3bd07ab 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java @@ -18,6 +18,8 @@ package at.gv.egiz.smcc;  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; @@ -178,13 +180,10 @@ public abstract class CardTest {    @Test(expected = CancelledException.class)    public void testSignSIGCancel() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {          SignatureCard signatureCard = createSignatureCard(); -        MessageDigest md = MessageDigest.getInstance("SHA-1"); -        byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -                PINProvider pinProvider = new PINProvider() {            @Override            public char[] providePIN(PINSpec spec, int retries) @@ -193,21 +192,19 @@ public abstract class CardTest {            }          }; -        signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, -            pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, pinProvider, +        null);        }    @Test(expected = CancelledException.class)    public void testSignDECCancel() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {          SignatureCard signatureCard = createSignatureCard(); -        MessageDigest md = MessageDigest.getInstance("SHA-1"); -        byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -                PINProvider pinProvider = new PINProvider() {            @Override            public char[] providePIN(PINSpec spec, int retries) @@ -216,21 +213,19 @@ public abstract class CardTest {            }          }; -        signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, -            pinProvider); +        signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +            .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, +            pinProvider, null);        }    @Test(expected = InterruptedException.class)    public void testSignSIGInterrrupted() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {          SignatureCard signatureCard = createSignatureCard(); -        MessageDigest md = MessageDigest.getInstance("SHA-1"); -        byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -                PINProvider pinProvider = new PINProvider() {            @Override            public char[] providePIN(PINSpec spec, int retries) @@ -239,21 +234,19 @@ public abstract class CardTest {            }          }; -        signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, -            pinProvider); +        signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +            .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, +            pinProvider, null);        }    @Test(expected = InterruptedException.class)    public void testSignDECInterrrupted() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {          SignatureCard signatureCard = createSignatureCard(); -        MessageDigest md = MessageDigest.getInstance("SHA-1"); -        byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -                PINProvider pinProvider = new PINProvider() {            @Override            public char[] providePIN(PINSpec spec, int retries) @@ -262,21 +255,19 @@ public abstract class CardTest {            }          }; -        signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, -            pinProvider); +        signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +            .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, +            pinProvider, null);        }    @Test(expected = CancelledException.class)    public void testSignSIGConcurrent() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {          final SignatureCard signatureCard = createSignatureCard(); -        MessageDigest md = MessageDigest.getInstance("SHA-1"); -        byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -                PINProvider pinProvider = new PINProvider() {            @Override            public char[] providePIN(PINSpec spec, int retries) @@ -294,21 +285,19 @@ public abstract class CardTest {            }          }; -        signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, -            pinProvider); +        signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +            .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, +            pinProvider, null);        }    @Test(expected = CancelledException.class)    public void testSignDECConcurrent() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {          final SignatureCard signatureCard = createSignatureCard(); -        MessageDigest md = MessageDigest.getInstance("SHA-1"); -        byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -                PINProvider pinProvider = new PINProvider() {            @Override            public char[] providePIN(PINSpec spec, int retries) @@ -326,8 +315,9 @@ public abstract class CardTest {            }          }; -        signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, -            pinProvider); +        signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +            .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, +            pinProvider, null);        } 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 90bb039e..56d1e4b2 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 @@ -21,6 +21,8 @@ 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; @@ -125,7 +127,7 @@ public abstract class ACOSCardTest extends CardTest {    @Test    public void testSignSIG() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      char[] pin = "123456".toCharArray(); @@ -134,11 +136,9 @@ public abstract class ACOSCardTest extends CardTest {      ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG);      appl.setPin(ACOSApplSIG.KID_PIN_SIG, pin); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - -    byte[] signature = signatureCard.createSignature(hash, -        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin)); +    byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), +        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null);      assertNotNull(signature); @@ -147,7 +147,7 @@ public abstract class ACOSCardTest extends CardTest {    @Test    public void testSignDEC() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      char[] pin = "1234".toCharArray(); @@ -156,11 +156,9 @@ public abstract class ACOSCardTest extends CardTest {      ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC);      appl.setPin(ACOSApplDEC.KID_PIN_DEC, pin); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - -    byte[] signature = signatureCard.createSignature(hash, -        KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin)); +    byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), +        KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null);      assertNotNull(signature); @@ -169,74 +167,66 @@ public abstract class ACOSCardTest extends CardTest {    @Test(expected = LockedException.class)    public void testSignSIGInvalidPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      SignatureCard signatureCard = createSignatureCard(); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -      TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); -    signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, -        pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, +        pinProvider, null);    }    @Test(expected = LockedException.class)    public void testSignDECInvalidPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      SignatureCard signatureCard = createSignatureCard(); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -      TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); -    signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, -        pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, +        pinProvider, null);    }    @Test(expected = LockedException.class)    public void testSignSIGBlockedPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      SignatureCard signatureCard = createSignatureCard();      CardEmul card = (CardEmul) signatureCard.getCard();      ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG);      appl.setPin(ACOSApplSIG.KID_PIN_SIG, null); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -      TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); -    signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, -        pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, +        pinProvider, null);    }    @Test(expected = LockedException.class)    public void testSignDECBlockedPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      SignatureCard signatureCard = createSignatureCard();      CardEmul card = (CardEmul) signatureCard.getCard();      ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC);      appl.setPin(ACOSApplDEC.KID_PIN_DEC, null); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -      TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); -    signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, -        pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, +        pinProvider, null);    } 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 89e2ca65..b7dc9a0c 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 @@ -20,6 +20,8 @@ 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; @@ -147,7 +149,7 @@ public class STARCOSCardTest extends CardTest {    @Test    public void testSignSichereSignatur() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      char[] pin = "123456".toCharArray(); @@ -156,11 +158,9 @@ public class STARCOSCardTest extends CardTest {      STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur);      appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, pin); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - -    byte[] signature = signatureCard.createSignature(hash, -        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin)); +    byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), +        KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null);      assertNotNull(signature); @@ -169,7 +169,7 @@ public class STARCOSCardTest extends CardTest {    @Test    public void testSignGewoehnlicheSignatur() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      char[] pin = "1234".toCharArray(); @@ -178,11 +178,9 @@ public class STARCOSCardTest extends CardTest {      STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel();      channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, pin); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - -    byte[] signature = signatureCard.createSignature(hash, -        KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin)); +    byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), +        KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null);      assertNotNull(signature); @@ -191,75 +189,67 @@ public class STARCOSCardTest extends CardTest {    @Test(expected = LockedException.class)    public void testSignSichereSignaturInvalidPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      SignatureCard signatureCard = createSignatureCard(); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -      TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); -    signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, -        pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, +        pinProvider, null);    }    @Test(expected = LockedException.class)    public void testSignGewoehnlicheSignaturInvalidPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      SignatureCard signatureCard = createSignatureCard(); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -      TestPINProvider pinProvider = new TestPINProvider("1234".toCharArray()); -    signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, -        pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, +        pinProvider, null);    }    @Test(expected = LockedException.class)    public void testSignSichereSignaturBlockedPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      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); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -      TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray());      assertTrue(pinProvider.getProvided() <= 0); -    signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, -        pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, +        pinProvider, null);    }    @Test(expected = LockedException.class)    public void testSignGewoehnlicheSignaturBlockedPin() throws SignatureCardException,        InterruptedException, CardNotSupportedException, -      NoSuchAlgorithmException, UnsupportedEncodingException { +      NoSuchAlgorithmException, IOException {      SignatureCard signatureCard = createSignatureCard();      CardEmul card = (CardEmul) signatureCard.getCard();      STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel();      channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, null); -    MessageDigest md = MessageDigest.getInstance("SHA-1"); -    byte[] hash = md.digest("MOCCA".getBytes("ASCII")); -      TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); -    signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, -        pinProvider); +    signatureCard.createSignature(new ByteArrayInputStream("MOCCA" +        .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, +        pinProvider, null);    } | 
