diff options
Diffstat (limited to 'smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java')
-rw-r--r-- | smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java | 223 |
1 files changed, 198 insertions, 25 deletions
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 2131a737..777299d9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java @@ -28,19 +28,189 @@ // package at.gv.egiz.smcc; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + import javax.smartcardio.ATR; import javax.smartcardio.Card; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A factory for creating {@link SignatureCard}s from {@link Card}s. + */ public class SignatureCardFactory { + + /** + * This class represents a supported smart card. + */ + private class SupportedCard { + + /** + * The ATR pattern. + */ + private byte[] atrPattern; + + /** + * The ATR mask. + */ + private byte[] atrMask; + + /** + * The implementation class. + */ + private String impl; - public static SignatureCardFactory getInstance() { - return new SignatureCardFactory(); + /** + * Creates a new SupportedCard instance with the given ATR pattern and mask + * und the corresponding implementation class. + * + * @param atrPattern + * the ATR pattern + * @param atrMask + * the ATR mask + * @param implementationClass + * the name of the implementation class + * + * @throws NullPointerException + * if <code>atrPattern</code> or <code>atrMask</code> is + * <code>null</code>. + * @throws IllegalArgumentException + * if the lengths of <code>atrPattern</code> and + * <code>atrMask</code> of not equal. + */ + public SupportedCard(byte[] atrPattern, byte[] atrMask, String implementationClass) { + if (atrPattern.length != atrMask.length) { + throw new IllegalArgumentException("Length of 'atr' and 'mask' must be equal."); + } + this.atrPattern = atrPattern; + this.atrMask = atrMask; + this.impl = implementationClass; + } + + /** + * Returns true if the given ATR matches the ATR pattern and mask this + * SupportedCard object. + * + * @param atr + * the ATR + * + * @return <code>true</code> if the given ATR matches the ATR pattern and + * mask of this SupportedCard object, or <code>false</code> + * otherwise. + */ + public boolean matches(ATR atr) { + + byte[] bytes = atr.getBytes(); + if (bytes == null) { + return false; + } + if (bytes.length < atrMask.length) { + // we cannot test for equal length here, as we get ATRs with + // additional bytes on systems using PCSClite (e.g. linux and OS X) sometimes + return false; + } + + int l = Math.min(atrMask.length, bytes.length); + for (int i = 0; i < l; i++) { + if ((bytes[i] & atrMask[i]) != atrPattern[i]) { + return false; + } + } + return true; + + } + + /** + * @return the corresponding implementation class. + */ + public String getImplementationClassName() { + return impl; + } + + } + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(SignatureCardFactory.class); + + /** + * The instance to be returned by {@link #getInstance()}. + */ + private static SignatureCardFactory instance; + + /** + * The list of supported smart cards. + */ + private List<SupportedCard> supportedCards; + + /** + * @return an instance of this SignatureCardFactory. + */ + public static synchronized SignatureCardFactory getInstance() { + if (instance == null) { + instance = new SignatureCardFactory(); + } + return instance; } + /** + * Private constructor. + */ private SignatureCardFactory() { + + supportedCards = new ArrayList<SupportedCard>(); + + // e-card + supportedCards.add(new SupportedCard( + // ATR (3b:bd:18:00:81:31:fe:45:80:51:02:00:00:00:00:00:00:00:00:00:00:00) + new byte[] { + (byte) 0x3b, (byte) 0xbd, (byte) 0x18, (byte) 0x00, (byte) 0x81, (byte) 0x31, (byte) 0xfe, (byte) 0x45, + (byte) 0x80, (byte) 0x51, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + }, + // mask (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00: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) 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( + // ATR (3b:bf:11:00:81:31:fe:45:45:50:41:00:00:00:00:00:00:00:00:00:00:00:00:00) + new byte[] { + (byte) 0x3b, (byte) 0xbf, (byte) 0x11, (byte) 0x00, (byte) 0x81, (byte) 0x31, (byte) 0xfe, (byte) 0x45, + (byte) 0x45, (byte) 0x50, (byte) 0x41, (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 (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00:00: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) 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.ACOSCard")); + } + /** + * Creates a SignatureCard instance with the given smart card. + * + * @param card + * the smart card, or <code>null</code> if a software card should be + * created + * + * @return a SignatureCard instance + * + * @throws CardNotSupportedException + * if no implementation of the given <code>card</code> could be + * found + */ public SignatureCard createSignatureCard(Card card) throws CardNotSupportedException { @@ -51,31 +221,34 @@ public class SignatureCardFactory { } ATR atr = card.getATR(); - byte[] historicalBytes = atr.getHistoricalBytes(); - if(historicalBytes == null || historicalBytes.length < 3) { - throw new CardNotSupportedException("Card not supported: ATR=" + toString(atr.getBytes())); + Iterator<SupportedCard> cards = supportedCards.iterator(); + while (cards.hasNext()) { + SupportedCard supportedCard = cards.next(); + if(supportedCard.matches(atr)) { + + ClassLoader cl = SignatureCardFactory.class.getClassLoader(); + SignatureCard sc; + try { + Class<?> scClass = cl.loadClass(supportedCard.getImplementationClassName()); + sc = (SignatureCard) scClass.newInstance(); + sc.init(card); + return sc; + + } catch (ClassNotFoundException e) { + log.warn("Cannot find signature card implementation class.", e); + throw new CardNotSupportedException("Cannot find signature card implementation class.", e); + } catch (InstantiationException e) { + log.warn("Failed to instantiate signature card implementation.", e); + throw new CardNotSupportedException("Failed to instantiate signature card implementation.", e); + } catch (IllegalAccessException e) { + log.warn("Failed to instantiate signature card implementation.", e); + throw new CardNotSupportedException("Failed to instantiate signature card implementation.", e); + } + + } } - int t = ((0xFF & (int) historicalBytes[0]) << 16) + - ((0xFF & (int) historicalBytes[1]) << 8) + - (0xFF & (int) historicalBytes[2]); - - SignatureCard sCard; - switch (t) { - case 0x455041 : - case 0x4D4341 : - sCard = new ACOSCard(); - break; - - case 0x805102 : - sCard = new STARCOSCard(); - break; - - default : - throw new CardNotSupportedException("Card not supported: ATR=" + toString(atr.getBytes())); - } - sCard.init(card); - return sCard; + throw new CardNotSupportedException("Card not supported: ATR=" + toString(atr.getBytes())); } |