summaryrefslogtreecommitdiff
path: root/smcc/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'smcc/src/main/java')
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java42
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java53
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java90
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/SWCard.java8
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java11
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);
-
+
}