summaryrefslogtreecommitdiff
path: root/smcc
diff options
context:
space:
mode:
Diffstat (limited to 'smcc')
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java16
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java302
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java9
-rw-r--r--smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java2
4 files changed, 225 insertions, 104 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 a63d4076..1ed5a177 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java
@@ -116,6 +116,14 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
private static final PINSpec INF_PIN_SPEC = new PINSpec(0, 8, "[0-9]",
"at/gv/egiz/smcc/ACOSCard", "inf.pin", KID_PIN_INF, AID_DEC);
+ static {
+ if (SignatureCardFactory.ENFORCE_RECOMMENDED_PIN_LENGTH) {
+ DEC_PIN_SPEC.setRecLength(4);
+ SIG_PIN_SPEC.setRecLength(6);
+ INF_PIN_SPEC.setRecLength(4);
+ }
+ }
+
/**
* The version of the card's digital signature application.
*/
@@ -390,10 +398,12 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
MessageDigest md;
try {
- if ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1".equals(alg)) {
+ if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)
+ && (alg == null || "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)) {
+ } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)
+ && (alg == null || "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)
@@ -401,7 +411,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC
&& "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)
+ } else if (KeyboxName.CERITIFIED_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
diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java b/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java
index 1812049c..f68edbed 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java
@@ -17,6 +17,7 @@
package at.gv.egiz.smcc;
import java.util.Locale;
+import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
@@ -25,113 +26,214 @@ import java.util.ResourceBundle;
*/
public class PINSpec {
- int minLength_ = 0;
+ /**
+ * The minimum PIN length.
+ */
+ protected int minLength = 0;
- int maxLength_ = -1;
+ /**
+ * The maximum PIN length or -1 if not specified.
+ */
+ protected int maxLength = -1;
- String rexepPattern_;
-
- String resourceBundleName_;
-
- String nameKey_;
-
- /** the localized, i.e. configurable length */
- String lengthKey_;
-
- byte kid_;
-
- byte[] context_aid_;
-
- /**
- *
- * @param minLenght
- * @param maxLength
- * @param rexepPattern
- * @param resourceBundle
- * @param name
- * @param kid the keyId for this pin
- */
- public PINSpec(int minLenght, int maxLength, String rexepPattern,
- String resourceBundleName, String resourceKey, byte kid, byte[] contextAID) {
-
- minLength_ = minLenght;
- maxLength_ = maxLength;
- rexepPattern_ = rexepPattern;
- resourceBundleName_ = resourceBundleName;
- nameKey_ = resourceKey + ".name";
- lengthKey_ = resourceKey + ".length";
- kid_ = kid;
- context_aid_ = contextAID;
- }
-
- public PINSpec(int minLenght, int maxLength, String rexepPattern,
- String name, byte kid, byte[] contextAID) {
-
- minLength_ = minLenght;
- maxLength_ = maxLength;
- rexepPattern_ = rexepPattern;
- nameKey_ = name + ".name";
- lengthKey_ = name + ".length";
- kid_ = kid;
- context_aid_ = contextAID;
- }
-
- public String getLocalizedName() {
-
- if (resourceBundleName_ != null) {
- ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName_);
- return resourceBundle.getString(nameKey_);
- } else {
- return nameKey_;
+ /**
+ * The recommended PIN length or -1 if not specified.
+ */
+ protected int recLength = -1;
+
+ /**
+ * The regular expression pattern of a single PIN digit or character.
+ */
+ protected String rexepPattern;
+
+ /**
+ * The name of the corresponding resource bundle.
+ */
+ protected String resourceBundleName;
+
+ /**
+ * The key of the PIN name in the resource bundle.
+ */
+ protected String nameKey;
+
+ /**
+ * The name of the PIN.
+ */
+ protected String name;
+
+ /**
+ * The key id to be used in VERIFY or CHANGE REFERENCE DATA APDUs.
+ */
+ protected byte kid;
+
+ /**
+ * The context AID of the key id.
+ */
+ protected byte[] context_aid;
+
+ /**
+ * Creates a new instance of this PINSpec with the given lengths, regular
+ * expression pattern, the ResourceBundle name and key to lookup the PIN name
+ * and the KID and AID.
+ *
+ * @param minLenght the minimum length of the PIN
+ * @param maxLength the maximum length of the PIN, or -1 if there is no maximum length
+ * @param rexepPattern the regular expression pattern of a single PIN digit or character
+ * @param resourceBundleName the name of a ResourceBundle for this PIN
+ * @param resourceKey the key to look up the (localized) name of this PIN
+ * @param kid the key id of the PIN
+ * @param contextAID the AID the KID is valid in
+ */
+ public PINSpec(int minLenght, int maxLength, String rexepPattern,
+ String resourceBundleName, String resourceKey, byte kid, byte[] contextAID) {
+
+ this.minLength = minLenght;
+ this.maxLength = maxLength;
+ this.rexepPattern = rexepPattern;
+ this.resourceBundleName = resourceBundleName;
+ this.nameKey = resourceKey + ".name";
+ this.kid = kid;
+ this.context_aid = contextAID;
+ }
+
+ /**
+ * Creates a new instance of this PINSpec with the given lengths, regular
+ * expression pattern, the name of the PIN and the KID and AID.
+ *
+ * @param minLenght the minimum length of the PIN
+ * @param maxLength the maximum length of the PIN, or -1 if there is no maximum length
+ * @param rexepPattern the regular expression pattern of a single PIN digit or character
+ * @param name the name of the PIN
+ * @param kid the key id of the PIN
+ * @param contextAID the AID the KID is valid in
+ */
+ public PINSpec(int minLenght, int maxLength, String rexepPattern,
+ String name, byte kid, byte[] contextAID) {
+
+ this.minLength = minLenght;
+ this.maxLength = maxLength;
+ this.rexepPattern = rexepPattern;
+ this.name = name;
+ this.kid = kid;
+ this.context_aid = contextAID;
+ }
+
+ /**
+ * This method sets the recommended PIN length.
+ *
+ * @param recLength the recommended PIN length
+ */
+ public void setRecLength(int recLength) {
+ this.recLength = recLength;
+ }
+
+ /**
+ * @return the localized (using the default locale) name of the PIN, or the
+ * name set by
+ * {@link #PINSpec(int, int, String, String, byte, byte[])}.
+ */
+ public String getLocalizedName() {
+ if (name != null) {
+ return name;
+ } else if (resourceBundleName != null){
+ try {
+ return ResourceBundle.getBundle(resourceBundleName).getString(nameKey);
+ } catch (MissingResourceException e) {
}
-
}
-
- public String getLocalizedName(Locale locale) {
-
- if (resourceBundleName_ != null) {
- ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName_, locale);
- return resourceBundle.getString(nameKey_);
- } else {
- return nameKey_;
+ return nameKey;
+ }
+
+ /**
+ * @param locale the locale for which the name should be returned
+ * @return the localized name of the PIN, or the name set by
+ * {@link #PINSpec(int, int, String, String, byte, byte[])}
+ */
+ public String getLocalizedName(Locale locale) {
+ if (name != null) {
+ return name;
+ } else if (resourceBundleName != null) {
+ try {
+ return ResourceBundle.getBundle(resourceBundleName, locale).getString(nameKey);
+ } catch (MissingResourceException e) {
}
-
- }
-
- public String getLocalizedLength() {
-
- if (resourceBundleName_ != null) {
- ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName_);
- return resourceBundle.getString(lengthKey_);
- } else {
- if (maxLength_ > minLength_) {
- return minLength_ + "-" + maxLength_;
- } else {
- return String.valueOf(minLength_);
- }
- }
-
}
-
- public int getMaxLength() {
- return maxLength_;
- }
-
- public int getMinLength() {
- return minLength_;
- }
-
- public String getRexepPattern() {
- return rexepPattern_;
- }
-
- public byte getKID() {
- return kid_;
+ return nameKey;
+ }
+
+ /**
+ * @return the recommended PIN length if specified and
+ * <code>recommended</code> is <code>true</code>, or
+ * <code>minLength</code>-<code>maxLength</code>
+ */
+ public String getLocalizedLength() {
+
+ if (recLength > 0) {
+ return "" + recLength;
+ } else if (maxLength == minLength) {
+ return "" + minLength;
+ } else if (maxLength > minLength) {
+ return minLength + "-" + maxLength;
+ } else {
+ return minLength + "+";
}
- public byte[] getContextAID() {
- return context_aid_;
- }
-
+ }
+
+ /**
+ * @return the minimum length of the PIN
+ */
+ public int getMinLength() {
+ return minLength;
+ }
+
+ /**
+ * @return the maximum length of the PIN, or -1 if not specified.
+ */
+ public int getMaxLength() {
+ return maxLength;
+ }
+
+ /**
+ * @return the minimum length of the PIN
+ */
+ public int getRecMinLength() {
+ return (recLength >= minLength) ? recLength : minLength;
+ }
+
+ /**
+ * @return the maximum length of the PIN
+ */
+ public int getRecMaxLength() {
+ return (recLength >= minLength) ? recLength : maxLength;
+ }
+
+ /**
+ * @return the recommended length of the PIN, or -1 if not specified
+ */
+ public int getRecLength() {
+ return recLength;
+ }
+
+ /**
+ * @return the regular expression pattern of one single digit or character
+ */
+ public String getRexepPattern() {
+ return rexepPattern;
+ }
+
+ /**
+ * @return the key id of the PIN
+ */
+ public byte getKID() {
+ return kid;
+ }
+
+ /**
+ * @return the AID the KID is valid in, or <code>null</code> if KID is global
+ */
+ public byte[] getContextAID() {
+ return context_aid;
+ }
}
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 01de8a77..880cab4b 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java
@@ -137,6 +137,13 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
new PINSpec(6, 12, "[0-9]",
"at/gv/egiz/smcc/STARCOSCard", "sig.pin", KID_PIN_SS, AID_DF_SS);
+ static {
+ if (SignatureCardFactory.ENFORCE_RECOMMENDED_PIN_LENGTH) {
+ CARD_PIN_SPEC.setRecLength(4);
+ SS_PIN_SPEC.setRecLength(6);
+ }
+ }
+
protected double version = 1.1;
/**
@@ -301,7 +308,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu
MessageDigest md = null;
try {
- if (version < 1.2 && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1".equals(alg)) {
+ if (version < 1.2 && (alg == null || "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
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 47053f98..405da7c0 100644
--- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java
+++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java
@@ -32,6 +32,8 @@ import org.apache.commons.logging.LogFactory;
* A factory for creating {@link SignatureCard}s from {@link Card}s.
*/
public class SignatureCardFactory {
+
+ public static boolean ENFORCE_RECOMMENDED_PIN_LENGTH = false;
/**
* This class represents a supported smart card.