From 32d17447a258188b2d534bcb0bf65a659ba7b7d0 Mon Sep 17 00:00:00 2001 From: mcentner Date: Fri, 29 Aug 2008 12:11:34 +0000 Subject: Initial import. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@1 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 259 +++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java new file mode 100644 index 00000000..91c873c9 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -0,0 +1,259 @@ +//Copyright (C) 2002 IAIK +//http://jce.iaik.at +// +//Copyright (C) 2003 Stiftung Secure Information and +// Communication Technologies SIC +//http://www.sic.st +// +//All rights reserved. +// +//This source is provided for inspection purposes and recompilation only, +//unless specified differently in a contract with IAIK. This source has to +//be kept in strict confidence and must not be disclosed to any third party +//under any circumstances. Redistribution in source and binary forms, with +//or without modification, are permitted in any case! +// +//THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +//SUCH DAMAGE. +// +// +package at.gv.egiz.smcc; + +import java.nio.ByteBuffer; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.logging.Logger; + +import javax.smartcardio.ATR; +import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; + +public abstract class AbstractSignatureCard implements SignatureCard { + + static Logger logger = Logger.getLogger(AbstractSignatureCard.class.getName()); + + private ResourceBundle i18n; + private String resourceBundleName; + + private Locale locale = Locale.getDefault(); + + int ifs_ = 254; + + Card card_; + + protected AbstractSignatureCard(String resourceBundleName) { + this.resourceBundleName = resourceBundleName; + } + + String toString(byte[] b) { + StringBuffer sb = new StringBuffer(); + if (b != null && b.length > 0) { + sb.append(Integer.toHexString((b[0] & 240) >> 4)); + sb.append(Integer.toHexString(b[0] & 15)); + } + for(int i = 1; i < b.length; i++) { + sb.append(':'); + sb.append(Integer.toHexString((b[i] & 240) >> 4)); + sb.append(Integer.toHexString(b[i] & 15)); + } + return sb.toString(); + } + + abstract byte[] selectFileAID(byte[] fid) throws CardException, SignatureCardException; + + abstract byte[] selectFileFID(byte[] fid) throws CardException, SignatureCardException; + + byte[] readBinary(CardChannel channel, int offset, int len) + throws CardException, SignatureCardException { + + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB0, + 0x7F & (offset >> 8), offset & 0xFF, len)); + if (resp.getSW() == 0x9000) { + return resp.getData(); + } else { + throw new SignatureCardException("Failed to read bytes (" + offset + "+" + + len + "): SW=" + Integer.toHexString(resp.getSW())); + } + + } + + int readBinary(int offset, int len, byte[] b) + throws CardException, SignatureCardException { + + if (b.length < len) { + throw new IllegalArgumentException( + "Length of b must not be less than len."); + } + + CardChannel channel = getCardChannel(); + + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB0, + 0x7F & (offset >> 8), offset & 0xFF, len)); + if (resp.getSW() == 0x9000) { + System.arraycopy(resp.getData(), 0, b, 0, len); + } + + return resp.getSW(); + + } + + byte[] readBinaryTLV(int maxSize, byte expectedType) throws CardException, SignatureCardException { + + CardChannel channel = getCardChannel(); + + // read first chunk + int len = Math.min(maxSize, ifs_); + byte[] chunk = readBinary(channel, 0, len); + if (chunk.length > 0 && chunk[0] != expectedType) { + return null; + } + int offset = chunk.length; + int actualSize = maxSize; + if (chunk.length > 3) { + if ((chunk[1] & 0x80) > 0) { + int octets = (0x0F & chunk[1]); + actualSize = 2 + octets; + for (int i = 1; i <= octets; i++) { + actualSize += (0xFF & chunk[i + 1]) << ((octets - i) * 8); + } + } else { + actualSize = 2 + chunk[1]; + } + } + ByteBuffer buffer = ByteBuffer.allocate(actualSize); + buffer.put(chunk, 0, Math.min(actualSize, chunk.length)); + while (offset < actualSize) { + len = Math.min(ifs_, actualSize - offset); + chunk = readBinary(channel, offset, len); + buffer.put(chunk); + offset += chunk.length; + } + return buffer.array(); + + } + + abstract int verifyPIN(PINProvider pinProvider, PINSpec spec, byte kid, int kfpc) throws CardException, SignatureCardException; + + public byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) throws SignatureCardException { + return readTLVFilePIN(aid, ef, (byte) 0, null, null, maxLength); + } + + public byte[] readTLVFilePIN(byte[] aid, byte[] ef, byte kid, + PINProvider provider, PINSpec spec, int maxLength) throws SignatureCardException { + + try { + + // SELECT FILE (AID) + byte[] rb = selectFileAID(aid); + if (rb[rb.length - 2] != (byte) 0x90 || + rb[rb.length - 1] != (byte) 0x00) { + + throw new SignatureCardException( + "SELECT FILE with " + + "AID=" + toString(aid) + " failed (" + + "SW=" + + Integer.toHexString( + (0xFF & (int) rb[rb.length - 1]) | + (0xFF & (int) rb[rb.length - 2]) << 8) + + ")."); + + } + + // SELECT FILE (EF) + rb = selectFileFID(ef); + if (rb[rb.length - 2] != (byte) 0x90 || + rb[rb.length - 1] != (byte) 0x00) { + + throw new SignatureCardException( + "SELECT FILE with " + + "FID=" + toString(ef) + " failed (" + + "SW=" + + Integer.toHexString( + (0xFF & (int) rb[rb.length - 1]) | + (0xFF & (int) rb[rb.length - 2]) << 8) + + ")."); + } + + // try to READ BINARY + int sw = readBinary(0, 1, new byte[1]); + if (provider != null && sw == 0x6982) { + + // VERIFY + int kfpc = -1; // unknown + while (true) { + kfpc = verifyPIN(provider, spec, kid, kfpc); + if (kfpc < -1) { + return null; + } else if (kfpc < 0) { + break; + } + } + } else if (sw != 0x9000) { + throw new SignatureCardException("READ BINARY failed (SW=" + + Integer.toHexString(sw) + ")."); + } + + // READ BINARY + byte[] data = readBinaryTLV(maxLength, (byte) 0x30); + + return data; + + + } catch (CardException e) { + throw new SignatureCardException("Failed to acces card.", e); + } + + } + + + ResponseAPDU transmit(CardChannel channel, CommandAPDU commandAPDU) throws CardException { + logger.fine(commandAPDU + "\n" + toString(commandAPDU.getBytes())); + long t0 = System.currentTimeMillis(); + ResponseAPDU responseAPDU = channel.transmit(commandAPDU); + long t1 = System.currentTimeMillis(); + logger.fine(responseAPDU + "\n[" + (t1 - t0) + "ms] " + toString(responseAPDU.getBytes())); + return responseAPDU; + } + + public void init(Card card) { + card_ = card; + ATR atr = card.getATR(); + byte[] atrBytes = atr.getBytes(); + if (atrBytes.length >= 6) { + ifs_ = 0xFF & atr.getBytes()[6]; + logger.finer("Setting IFS (information field size) to " + ifs_); + } + } + + CardChannel getCardChannel() { + return card_.getBasicChannel(); + } + + + @Override + public void setLocale(Locale locale) { + if (locale == null) { + throw new NullPointerException("Locale must not be set to null"); + } + this.locale = locale; + } + + protected ResourceBundle getResourceBundle() { + if (i18n == null) { + i18n = ResourceBundle.getBundle(resourceBundleName, locale); + } + return i18n; + } +} -- cgit v1.2.3 From 62dffe15b09010e64a886a936d549239f441cd31 Mon Sep 17 00:00:00 2001 From: wbauer Date: Fri, 10 Oct 2008 09:12:11 +0000 Subject: added a reset command git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@96 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 229 +++++++++++---------- 1 file changed, 123 insertions(+), 106 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 91c873c9..ab6932d7 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -40,40 +40,45 @@ import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + public abstract class AbstractSignatureCard implements SignatureCard { - static Logger logger = Logger.getLogger(AbstractSignatureCard.class.getName()); - + private static Log log = LogFactory.getLog(AbstractSignatureCard.class); + private ResourceBundle i18n; private String resourceBundleName; private Locale locale = Locale.getDefault(); - + int ifs_ = 254; - + Card card_; - + protected AbstractSignatureCard(String resourceBundleName) { this.resourceBundleName = resourceBundleName; } - + String toString(byte[] b) { StringBuffer sb = new StringBuffer(); if (b != null && b.length > 0) { sb.append(Integer.toHexString((b[0] & 240) >> 4)); sb.append(Integer.toHexString(b[0] & 15)); } - for(int i = 1; i < b.length; i++) { + for (int i = 1; i < b.length; i++) { sb.append(':'); sb.append(Integer.toHexString((b[i] & 240) >> 4)); sb.append(Integer.toHexString(b[i] & 15)); } return sb.toString(); } - - abstract byte[] selectFileAID(byte[] fid) throws CardException, SignatureCardException; - abstract byte[] selectFileFID(byte[] fid) throws CardException, SignatureCardException; + abstract byte[] selectFileAID(byte[] fid) throws CardException, + SignatureCardException; + + abstract byte[] selectFileFID(byte[] fid) throws CardException, + SignatureCardException; byte[] readBinary(CardChannel channel, int offset, int len) throws CardException, SignatureCardException { @@ -88,31 +93,32 @@ public abstract class AbstractSignatureCard implements SignatureCard { } } - - int readBinary(int offset, int len, byte[] b) - throws CardException, SignatureCardException { - if (b.length < len) { - throw new IllegalArgumentException( - "Length of b must not be less than len."); - } + int readBinary(int offset, int len, byte[] b) throws CardException, + SignatureCardException { - CardChannel channel = getCardChannel(); - - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB0, - 0x7F & (offset >> 8), offset & 0xFF, len)); - if (resp.getSW() == 0x9000) { - System.arraycopy(resp.getData(), 0, b, 0, len); - } - - return resp.getSW(); + if (b.length < len) { + throw new IllegalArgumentException( + "Length of b must not be less than len."); + } + + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB0, + 0x7F & (offset >> 8), offset & 0xFF, len)); + if (resp.getSW() == 0x9000) { + System.arraycopy(resp.getData(), 0, b, 0, len); } - byte[] readBinaryTLV(int maxSize, byte expectedType) throws CardException, SignatureCardException { + return resp.getSW(); + + } + + byte[] readBinaryTLV(int maxSize, byte expectedType) throws CardException, + SignatureCardException { CardChannel channel = getCardChannel(); - + // read first chunk int len = Math.min(maxSize, ifs_); byte[] chunk = readBinary(channel, 0, len); @@ -141,89 +147,88 @@ public abstract class AbstractSignatureCard implements SignatureCard { offset += chunk.length; } return buffer.array(); - + } - - abstract int verifyPIN(PINProvider pinProvider, PINSpec spec, byte kid, int kfpc) throws CardException, SignatureCardException; - public byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) throws SignatureCardException { - return readTLVFilePIN(aid, ef, (byte) 0, null, null, maxLength); - } - - public byte[] readTLVFilePIN(byte[] aid, byte[] ef, byte kid, - PINProvider provider, PINSpec spec, int maxLength) throws SignatureCardException { - - try { - - // SELECT FILE (AID) - byte[] rb = selectFileAID(aid); - if (rb[rb.length - 2] != (byte) 0x90 || - rb[rb.length - 1] != (byte) 0x00) { - - throw new SignatureCardException( - "SELECT FILE with " + - "AID=" + toString(aid) + " failed (" + - "SW=" + - Integer.toHexString( - (0xFF & (int) rb[rb.length - 1]) | - (0xFF & (int) rb[rb.length - 2]) << 8) + - ")."); - - } - - // SELECT FILE (EF) - rb = selectFileFID(ef); - if (rb[rb.length - 2] != (byte) 0x90 || - rb[rb.length - 1] != (byte) 0x00) { - - throw new SignatureCardException( - "SELECT FILE with " + - "FID=" + toString(ef) + " failed (" + - "SW=" + - Integer.toHexString( - (0xFF & (int) rb[rb.length - 1]) | - (0xFF & (int) rb[rb.length - 2]) << 8) + - ")."); - } - - // try to READ BINARY - int sw = readBinary(0, 1, new byte[1]); - if (provider != null && sw == 0x6982) { - - // VERIFY - int kfpc = -1; // unknown - while (true) { - kfpc = verifyPIN(provider, spec, kid, kfpc); - if (kfpc < -1) { - return null; - } else if (kfpc < 0) { - break; - } - } - } else if (sw != 0x9000) { - throw new SignatureCardException("READ BINARY failed (SW=" + - Integer.toHexString(sw) + ")."); - } - - // READ BINARY - byte[] data = readBinaryTLV(maxLength, (byte) 0x30); - - return data; - - - } catch (CardException e) { - throw new SignatureCardException("Failed to acces card.", e); + abstract int verifyPIN(PINProvider pinProvider, PINSpec spec, byte kid, + int kfpc) throws CardException, SignatureCardException; + + public byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) + throws SignatureCardException { + return readTLVFilePIN(aid, ef, (byte) 0, null, null, maxLength); + } + + public byte[] readTLVFilePIN(byte[] aid, byte[] ef, byte kid, + PINProvider provider, PINSpec spec, int maxLength) + throws SignatureCardException { + + try { + + // SELECT FILE (AID) + byte[] rb = selectFileAID(aid); + if (rb[rb.length - 2] != (byte) 0x90 || rb[rb.length - 1] != (byte) 0x00) { + + throw new SignatureCardException("SELECT FILE with " + + "AID=" + + toString(aid) + + " failed (" + + "SW=" + + Integer.toHexString((0xFF & (int) rb[rb.length - 1]) + | (0xFF & (int) rb[rb.length - 2]) << 8) + ")."); + + } + + // SELECT FILE (EF) + rb = selectFileFID(ef); + if (rb[rb.length - 2] != (byte) 0x90 || rb[rb.length - 1] != (byte) 0x00) { + + throw new SignatureCardException("SELECT FILE with " + + "FID=" + + toString(ef) + + " failed (" + + "SW=" + + Integer.toHexString((0xFF & (int) rb[rb.length - 1]) + | (0xFF & (int) rb[rb.length - 2]) << 8) + ")."); + } + + // try to READ BINARY + int sw = readBinary(0, 1, new byte[1]); + if (provider != null && sw == 0x6982) { + + // VERIFY + int kfpc = -1; // unknown + while (true) { + kfpc = verifyPIN(provider, spec, kid, kfpc); + if (kfpc < -1) { + return null; + } else if (kfpc < 0) { + break; + } } + } else if (sw != 0x9000) { + throw new SignatureCardException("READ BINARY failed (SW=" + + Integer.toHexString(sw) + ")."); + } + + // READ BINARY + byte[] data = readBinaryTLV(maxLength, (byte) 0x30); + return data; + + } catch (CardException e) { + throw new SignatureCardException("Failed to acces card.", e); } - - ResponseAPDU transmit(CardChannel channel, CommandAPDU commandAPDU) throws CardException { - logger.fine(commandAPDU + "\n" + toString(commandAPDU.getBytes())); + } + + ResponseAPDU transmit(CardChannel channel, CommandAPDU commandAPDU) + throws CardException { + log.trace(commandAPDU + "\n" + toString(commandAPDU.getBytes())); long t0 = System.currentTimeMillis(); ResponseAPDU responseAPDU = channel.transmit(commandAPDU); long t1 = System.currentTimeMillis(); - logger.fine(responseAPDU + "\n[" + (t1 - t0) + "ms] " + toString(responseAPDU.getBytes())); + log.trace(responseAPDU + "\n[" + (t1 - t0) + "ms] " + + toString(responseAPDU.getBytes())); return responseAPDU; } @@ -233,15 +238,14 @@ public abstract class AbstractSignatureCard implements SignatureCard { byte[] atrBytes = atr.getBytes(); if (atrBytes.length >= 6) { ifs_ = 0xFF & atr.getBytes()[6]; - logger.finer("Setting IFS (information field size) to " + ifs_); + log.trace("Setting IFS (information field size) to " + ifs_); } } CardChannel getCardChannel() { return card_.getBasicChannel(); } - - + @Override public void setLocale(Locale locale) { if (locale == null) { @@ -249,11 +253,24 @@ public abstract class AbstractSignatureCard implements SignatureCard { } this.locale = locale; } - + protected ResourceBundle getResourceBundle() { if (i18n == null) { i18n = ResourceBundle.getBundle(resourceBundleName, locale); } return i18n; } + + @Override + public void reset() { + log.debug("Resetting card"); + if (card_ != null) { + try { + card_.disconnect(true); + } catch (CardException e) { + log.info("Error while resetting card", e); + } + } + } + } -- cgit v1.2.3 From 8852be703a5cacaf271575ccee04bbe27612d16b Mon Sep 17 00:00:00 2001 From: wbauer Date: Fri, 10 Oct 2008 12:35:07 +0000 Subject: Improved Quit Handling for multiple applet instances git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@101 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 ab6932d7..7f3a3b1c 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -262,11 +262,11 @@ public abstract class AbstractSignatureCard implements SignatureCard { } @Override - public void reset() { - log.debug("Resetting card"); + public void disconnect(boolean reset) { + log.debug("Disconnect called"); if (card_ != null) { try { - card_.disconnect(true); + card_.disconnect(reset); } catch (CardException e) { log.info("Error while resetting card", e); } -- cgit v1.2.3 From ef8dc449ddc60008bce9264c73b4162cc487c174 Mon Sep 17 00:00:00 2001 From: wbauer Date: Thu, 16 Oct 2008 07:51:13 +0000 Subject: Changed STAL Handler from static registration to one Object per STAL instance git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@121 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 7f3a3b1c..77a3e2ea 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -267,7 +267,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { if (card_ != null) { try { card_.disconnect(reset); - } catch (CardException e) { + } catch (Exception e) { log.info("Error while resetting card", e); } } -- cgit v1.2.3 From c2ae3db1bc6dcb8ba3eb3461c05e293917c004ca Mon Sep 17 00:00:00 2001 From: mcentner Date: Thu, 30 Oct 2008 10:33:29 +0000 Subject: Updated SMCC to use exclusive access and to throw exceptions upon locked or not activated cards. Improved locale support in the security layer request and response processing. Fixed issue in STAL which prevented the use of RSA-SHA1 signatures. Added additional parameters to the applet test pages. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@128 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 169 ++++++++++++++++----- 1 file changed, 134 insertions(+), 35 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 77a3e2ea..cebc63fc 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -31,7 +31,6 @@ package at.gv.egiz.smcc; import java.nio.ByteBuffer; import java.util.Locale; import java.util.ResourceBundle; -import java.util.logging.Logger; import javax.smartcardio.ATR; import javax.smartcardio.Card; @@ -60,7 +59,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { this.resourceBundleName = resourceBundleName; } - String toString(byte[] b) { + protected String toString(byte[] b) { StringBuffer sb = new StringBuffer(); if (b != null && b.length > 0) { sb.append(Integer.toHexString((b[0] & 240) >> 4)); @@ -74,13 +73,46 @@ public abstract class AbstractSignatureCard implements SignatureCard { return sb.toString(); } - abstract byte[] selectFileAID(byte[] fid) throws CardException, + protected abstract byte[] selectFileAID(byte[] fid) throws CardException, SignatureCardException; - abstract byte[] selectFileFID(byte[] fid) throws CardException, + protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException; - byte[] readBinary(CardChannel channel, int offset, int len) + /** + * VERIFY PIN + * + *

+ * Implementations of this method should call + * {@link PINProvider#providePIN(PINSpec, int)} to retrieve the PIN entered by + * the user and VERIFY PIN on the smart card until the PIN has been + * successfully verified. + *

+ * + * @param pinProvider + * the PINProvider + * @param spec + * the PINSpec + * @param kid + * the key ID (KID) of the PIN to verify + * + * @throws CardException + * if smart card communication fails + * + * @throws CancelledException + * if the PINProvider indicated that the user canceled the PIN entry + * @throws NotActivatedException + * if the card application has not been activated + * @throws LockedException + * if the card application is locked + * + * @throws SignatureCardException + * if VERIFY PIN fails + */ + protected abstract void verifyPIN(PINProvider pinProvider, PINSpec spec, + byte kid) throws CardException, SignatureCardException; + + protected byte[] readBinary(CardChannel channel, int offset, int len) throws CardException, SignatureCardException { ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB0, @@ -94,7 +126,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { } - int readBinary(int offset, int len, byte[] b) throws CardException, + protected int readBinary(int offset, int len, byte[] b) throws CardException, SignatureCardException { if (b.length < len) { @@ -114,7 +146,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { } - byte[] readBinaryTLV(int maxSize, byte expectedType) throws CardException, + protected byte[] readBinaryTLV(int maxSize, byte expectedType) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); @@ -150,15 +182,38 @@ public abstract class AbstractSignatureCard implements SignatureCard { } - abstract int verifyPIN(PINProvider pinProvider, PINSpec spec, byte kid, - int kfpc) throws CardException, SignatureCardException; - - public byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) + /** + * Read the content of a TLV file. + * + * @param aid the application ID (AID) + * @param ef the elementary file (EF) + * @param maxLength the maximum length of the file + * + * @return the content of the file + * + * @throws SignatureCardException + */ + protected byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) throws SignatureCardException { return readTLVFilePIN(aid, ef, (byte) 0, null, null, maxLength); } - public byte[] readTLVFilePIN(byte[] aid, byte[] ef, byte kid, + + /** + * Read the content of a TLV file wich may require a PIN. + * + * @param aid the application ID (AID) + * @param ef the elementary file (EF) + * @param kid the key ID (KID) of the corresponding PIN + * @param provider the PINProvider + * @param spec the PINSpec + * @param maxLength the maximum length of the file + * + * @return the content of the file + * + * @throws SignatureCardException + */ + protected byte[] readTLVFilePIN(byte[] aid, byte[] ef, byte kid, PINProvider provider, PINSpec spec, int maxLength) throws SignatureCardException { @@ -179,33 +234,38 @@ public abstract class AbstractSignatureCard implements SignatureCard { } // SELECT FILE (EF) - rb = selectFileFID(ef); - if (rb[rb.length - 2] != (byte) 0x90 || rb[rb.length - 1] != (byte) 0x00) { + ResponseAPDU resp = selectFileFID(ef); + if (resp.getSW() == 0x6a82) { + + // EF not found + throw new FileNotFoundException("EF " + toString(ef) + " not found."); + + } else if (resp.getSW() != 0x9000) { throw new SignatureCardException("SELECT FILE with " + "FID=" + toString(ef) + " failed (" + "SW=" - + Integer.toHexString((0xFF & (int) rb[rb.length - 1]) - | (0xFF & (int) rb[rb.length - 2]) << 8) + ")."); + + Integer.toHexString(resp.getSW()) + ")."); + } // try to READ BINARY - int sw = readBinary(0, 1, new byte[1]); + byte[] b = new byte[1]; + int sw = readBinary(0, 1, b); + if (provider != null && sw == 0x6982) { // VERIFY - int kfpc = -1; // unknown - while (true) { - kfpc = verifyPIN(provider, spec, kid, kfpc); - if (kfpc < -1) { - return null; - } else if (kfpc < 0) { - break; - } + verifyPIN(provider, spec, kid); + + } else if (sw == 0x9000) { + // not expected type + if (b[0] != 0x30) { + throw new NotActivatedException(); } - } else if (sw != 0x9000) { + } else { throw new SignatureCardException("READ BINARY failed (SW=" + Integer.toHexString(sw) + ")."); } @@ -221,17 +281,56 @@ public abstract class AbstractSignatureCard implements SignatureCard { } - ResponseAPDU transmit(CardChannel channel, CommandAPDU commandAPDU) + /** + * Transmit the given command APDU using the given card channel. + * + * @param channel + * the card channel + * @param commandAPDU + * the command APDU + * @param logData + * true if command APDU data may be logged, or + * false otherwise + * + * @return the corresponding response APDU + * + * @throws CardException + * if smart card communication fails + */ + protected ResponseAPDU transmit(CardChannel channel, CommandAPDU commandAPDU, boolean logData) + throws CardException { + + if (log.isTraceEnabled()) { + log.trace(commandAPDU + + (logData ? "\n" + toString(commandAPDU.getBytes()) : "")); + long t0 = System.currentTimeMillis(); + ResponseAPDU responseAPDU = channel.transmit(commandAPDU); + long t1 = System.currentTimeMillis(); + log.trace(responseAPDU + "\n[" + (t1 - t0) + "ms] " + + (logData ? "\n" + toString(responseAPDU.getBytes()) : "")); + return responseAPDU; + } else { + return channel.transmit(commandAPDU); + } + + } + + /** + * Transmit the given command APDU using the given card channel. + * + * @param channel the card channel + * @param commandAPDU the command APDU + * + * @return the corresponding response APDU + * + * @throws CardException if smart card communication fails + */ + protected ResponseAPDU transmit(CardChannel channel, CommandAPDU commandAPDU) throws CardException { - log.trace(commandAPDU + "\n" + toString(commandAPDU.getBytes())); - long t0 = System.currentTimeMillis(); - ResponseAPDU responseAPDU = channel.transmit(commandAPDU); - long t1 = System.currentTimeMillis(); - log.trace(responseAPDU + "\n[" + (t1 - t0) + "ms] " - + toString(responseAPDU.getBytes())); - return responseAPDU; + return transmit(channel, commandAPDU, true); } + public void init(Card card) { card_ = card; ATR atr = card.getATR(); @@ -242,7 +341,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { } } - CardChannel getCardChannel() { + protected CardChannel getCardChannel() { return card_.getBasicChannel(); } -- cgit v1.2.3 From e4a47aa9393d74647f4f0c66b54dc4519fed492f Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 11 Nov 2008 12:16:00 +0000 Subject: Interrupt in waitForAction (applet closed) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@162 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 cebc63fc..b828e8cd 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -110,7 +110,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * if VERIFY PIN fails */ protected abstract void verifyPIN(PINProvider pinProvider, PINSpec spec, - byte kid) throws CardException, SignatureCardException; + byte kid) throws CardException, SignatureCardException, InterruptedException; protected byte[] readBinary(CardChannel channel, int offset, int len) throws CardException, SignatureCardException { @@ -194,7 +194,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws SignatureCardException */ protected byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) - throws SignatureCardException { + throws SignatureCardException, InterruptedException { return readTLVFilePIN(aid, ef, (byte) 0, null, null, maxLength); } @@ -215,7 +215,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { */ protected byte[] readTLVFilePIN(byte[] aid, byte[] ef, byte kid, PINProvider provider, PINSpec spec, int maxLength) - throws SignatureCardException { + throws SignatureCardException, InterruptedException { try { -- cgit v1.2.3 From 2df9621154ad057f6cace73efe49c9ef42515fde Mon Sep 17 00:00:00 2001 From: mcentner Date: Tue, 9 Dec 2008 08:14:43 +0000 Subject: Refactored STAL interface. Additional infobox functionality. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@236 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 30 ++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 b828e8cd..e34c4899 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -36,6 +36,7 @@ import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; @@ -53,7 +54,12 @@ public abstract class AbstractSignatureCard implements SignatureCard { int ifs_ = 254; - Card card_; + private Card card_; + + /** + * The card terminal that connects the {@link #card_}. + */ + private CardTerminal cardTerminal; protected AbstractSignatureCard(String resourceBundleName) { this.resourceBundleName = resourceBundleName; @@ -331,8 +337,9 @@ public abstract class AbstractSignatureCard implements SignatureCard { } - public void init(Card card) { + public void init(Card card, CardTerminal cardTerminal) { card_ = card; + this.cardTerminal = cardTerminal; ATR atr = card.getATR(); byte[] atrBytes = atr.getBytes(); if (atrBytes.length >= 6) { @@ -340,6 +347,11 @@ public abstract class AbstractSignatureCard implements SignatureCard { log.trace("Setting IFS (information field size) to " + ifs_); } } + + @Override + public Card getCard() { + return card_; + } protected CardChannel getCardChannel() { return card_.getBasicChannel(); @@ -372,4 +384,18 @@ public abstract class AbstractSignatureCard implements SignatureCard { } } + @Override + public void reset() throws SignatureCardException { + try { + log.debug("Disconnect and reset smart card."); + card_.disconnect(true); + log.debug("Reconnect smart card."); + if (cardTerminal != null) { + card_ = cardTerminal.connect("*"); + } + } catch (CardException e) { + throw new SignatureCardException("Failed to reset card.", e); + } + } + } -- cgit v1.2.3 From 887f6727479f3ae3d89a08ba619f9382b450e4c1 Mon Sep 17 00:00:00 2001 From: mcentner Date: Fri, 12 Dec 2008 11:48:47 +0000 Subject: Updated SMCC to support non-blocking PIN entry. Added SV-Personendaten infobox implementation. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@248 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 214 ++++++++++++--------- 1 file changed, 124 insertions(+), 90 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 e34c4899..633cc90d 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -28,6 +28,8 @@ // package at.gv.egiz.smcc; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.util.Locale; import java.util.ResourceBundle; @@ -79,45 +81,56 @@ public abstract class AbstractSignatureCard implements SignatureCard { return sb.toString(); } - protected abstract byte[] selectFileAID(byte[] fid) throws CardException, - SignatureCardException; - - protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, - SignatureCardException; - /** - * VERIFY PIN + * Select an application using AID as DF name according to ISO/IEC 7816-4 + * section 8.2.2.2. * - *

- * Implementations of this method should call - * {@link PINProvider#providePIN(PINSpec, int)} to retrieve the PIN entered by - * the user and VERIFY PIN on the smart card until the PIN has been - * successfully verified. - *

+ * @param dfName + * AID of the application to be selected * - * @param pinProvider - * the PINProvider - * @param spec - * the PINSpec - * @param kid - * the key ID (KID) of the PIN to verify + * @return the response data of the response APDU if SW=0x9000 * * @throws CardException - * if smart card communication fails - * - * @throws CancelledException - * if the PINProvider indicated that the user canceled the PIN entry - * @throws NotActivatedException - * if the card application has not been activated - * @throws LockedException - * if the card application is locked + * if card communication fails * * @throws SignatureCardException - * if VERIFY PIN fails + * if application selection fails (e.g. an application with the + * given AID is not present on the card) */ - protected abstract void verifyPIN(PINProvider pinProvider, PINSpec spec, - byte kid) throws CardException, SignatureCardException, InterruptedException; + protected byte[] selectFileAID(byte[] dfName) throws CardException, SignatureCardException { + CardChannel channel = getCardChannel(); + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x04, + 0x00, dfName, 256)); + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("Failed to select application AID=" + + toString(dfName) + ": SW=" + Integer.toHexString(resp.getSW()) + "."); + } else { + return resp.getBytes(); + } + } + + protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, + SignatureCardException; + protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException; + + + protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { + return readRecord(getCardChannel(), recordNumber); + } + + protected byte[] readRecord(CardChannel channel, int recordNumber) throws SignatureCardException, CardException { + + ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB2, + recordNumber, 0x04, 256)); + if (resp.getSW() == 0x9000) { + return resp.getData(); + } else { + throw new SignatureCardException("Failed to read records. SW=" + Integer.toHexString(resp.getSW())); + } + + } + protected byte[] readBinary(CardChannel channel, int offset, int len) throws CardException, SignatureCardException { @@ -125,6 +138,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { 0x7F & (offset >> 8), offset & 0xFF, len)); if (resp.getSW() == 0x9000) { return resp.getData(); + } else if (resp.getSW() == 0x6982) { + throw new SecurityStatusNotSatisfiedException(); } else { throw new SignatureCardException("Failed to read bytes (" + offset + "+" + len + "): SW=" + Integer.toHexString(resp.getSW())); @@ -188,43 +203,10 @@ public abstract class AbstractSignatureCard implements SignatureCard { } - /** - * Read the content of a TLV file. - * - * @param aid the application ID (AID) - * @param ef the elementary file (EF) - * @param maxLength the maximum length of the file - * - * @return the content of the file - * - * @throws SignatureCardException - */ - protected byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) - throws SignatureCardException, InterruptedException { - return readTLVFilePIN(aid, ef, (byte) 0, null, null, maxLength); - } - - - /** - * Read the content of a TLV file wich may require a PIN. - * - * @param aid the application ID (AID) - * @param ef the elementary file (EF) - * @param kid the key ID (KID) of the corresponding PIN - * @param provider the PINProvider - * @param spec the PINSpec - * @param maxLength the maximum length of the file - * - * @return the content of the file - * - * @throws SignatureCardException - */ - protected byte[] readTLVFilePIN(byte[] aid, byte[] ef, byte kid, - PINProvider provider, PINSpec spec, int maxLength) - throws SignatureCardException, InterruptedException { - + protected byte[] readRecords(byte[] aid, byte[] ef, int start, int end) throws SignatureCardException, InterruptedException { + try { - + // SELECT FILE (AID) byte[] rb = selectFileAID(aid); if (rb[rb.length - 2] != (byte) 0x90 || rb[rb.length - 1] != (byte) 0x00) { @@ -256,37 +238,89 @@ public abstract class AbstractSignatureCard implements SignatureCard { + Integer.toHexString(resp.getSW()) + ")."); } - - // try to READ BINARY - byte[] b = new byte[1]; - int sw = readBinary(0, 1, b); - if (provider != null && sw == 0x6982) { - - // VERIFY - verifyPIN(provider, spec, kid); - - } else if (sw == 0x9000) { - // not expected type - if (b[0] != 0x30) { - throw new NotActivatedException(); - } - } else { - throw new SignatureCardException("READ BINARY failed (SW=" - + Integer.toHexString(sw) + ")."); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + + for (int i = start; i <= end; i++) { + bytes.write(readRecord(i)); } - - // READ BINARY - byte[] data = readBinaryTLV(maxLength, (byte) 0x30); - - return data; - + + return bytes.toByteArray(); + } catch (CardException e) { throw new SignatureCardException("Failed to acces card.", e); + } catch (IOException e) { + throw new SignatureCardException("Failed to read records.", e); } - + + } + + /** + * Read the content of a TLV file. + * + * @param aid the application ID (AID) + * @param ef the elementary file (EF) + * @param maxLength the maximum length of the file + * + * @return the content of the file + * + * @throws SignatureCardException + * @throws CardException + */ + protected byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) + throws SignatureCardException, InterruptedException, CardException { + return readTLVFile(aid, ef, null, (byte) 0, maxLength); } + /** + * Read the content of a TLV file wich may require a PIN. + * + * @param aid the application ID (AID) + * @param ef the elementary file (EF) + * @param kid the key ID (KID) of the corresponding PIN + * @param provider the PINProvider + * @param spec the PINSpec + * @param maxLength the maximum length of the file + * + * @return the content of the file + * + * @throws SignatureCardException + * @throws CardException + */ + protected byte[] readTLVFile(byte[] aid, byte[] ef, String pin, byte kid, int maxLength) + throws SignatureCardException, InterruptedException, CardException { + + + // SELECT FILE (AID) + selectFileAID(aid); + + // SELECT FILE (EF) + ResponseAPDU resp = selectFileFID(ef); + if (resp.getSW() == 0x6a82) { + // EF not found + throw new FileNotFoundException("EF " + toString(ef) + " not found."); + } else if (resp.getSW() != 0x9000) { + throw new SignatureCardException("SELECT FILE with " + + "FID=" + + toString(ef) + + " failed (" + + "SW=" + + Integer.toHexString(resp.getSW()) + ")."); + } + + // VERIFY + if (pin != null) { + int retries = verifyPIN(pin, kid); + if (retries != -1) { + throw new VerificationFailedException(retries); + } + } + + return readBinaryTLV(maxLength, (byte) 0x30); + + + } + /** * Transmit the given command APDU using the given card channel. * -- cgit v1.2.3 From 8596426d5daf291618b5e407bc9f804aa217b24a Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 11 Feb 2009 20:10:15 +0000 Subject: prepare for pin management git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@301 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 633cc90d..67f090a5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -112,7 +112,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException; - protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException; + // made public +// protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException; protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { -- cgit v1.2.3 From 6576428966f1e3d688269a407b072fb01f9f7647 Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 26 Feb 2009 19:39:00 +0000 Subject: 1.1 candidate (activation) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@309 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 67f090a5..cb068725 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -31,7 +31,11 @@ package at.gv.egiz.smcc; 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; @@ -49,6 +53,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); + protected List pinSpecs = new ArrayList(); + private ResourceBundle i18n; private String resourceBundleName; @@ -433,4 +439,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { } } + @Override + public List getPINSpecs() { + return pinSpecs; + } } -- cgit v1.2.3 From a8690cc956924e1d83b0c45d21995ee2e10fbba2 Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 4 Mar 2009 16:44:34 +0000 Subject: 1.1-rc3 git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@311 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 53 +++++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 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); + } -- cgit v1.2.3 From e177419331b8849497d25d3eb1866c5dc715bc88 Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 6 Mar 2009 14:53:37 +0000 Subject: 1.1-rc4 git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@312 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 57 +++++++++------------- 1 file changed, 23 insertions(+), 34 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 63301bd1..39952bb9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -37,6 +37,8 @@ import java.util.List; import java.util.Locale; import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; @@ -117,8 +119,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException; - // made public -// protected abstract int verifyPIN(String pin, byte kid) throws CardException, SignatureCardException; + protected abstract int verifyPIN(String pin, byte kid) + throws LockedException, NotActivatedException, SignatureCardException; protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { @@ -321,7 +323,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { throw new VerificationFailedException(retries); } } - + return readBinaryTLV(maxLength, (byte) 0x30); @@ -443,53 +445,40 @@ public abstract class AbstractSignatureCard implements SignatureCard { return pinSpecs; } - public void changePIN(byte kid, byte[] contextAID, String oldPIN, String newPIN) throws SignatureCardException, VerificationFailedException { + @Override + public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { + Card icc = getCard(); try { icc.beginExclusive(); CardChannel channel = icc.getBasicChannel(); - if (contextAID != null) { + if (pinSpec.getContextAID() != null) { ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID)); + new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); if (responseAPDU.getSW() != 0x9000) { icc.endExclusive(); - String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + - ": Failed to select AID " + SMCCHelper.toString(contextAID) + + String msg = "Failed to verify PIN " + + SMCCHelper.toString(new byte[]{pinSpec.getKID()}) + + ": Failed to verify AID " + + SMCCHelper.toString(pinSpec.getContextAID()) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); log.error(msg); throw new SignatureCardException(msg); } } + return verifyPIN(pin, pinSpec.getKID()); - 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 verify pinspec: " + ex.getMessage(), ex); + throw new SignatureCardException(ex); + } finally { + try { + icc.endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); } - } catch (CardException ex) { - log.error("Failed to change PIN: " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); } } - - abstract byte[] encodePINBlock(String pin); - } -- cgit v1.2.3 From 2a1df5e58e44f8d77f34eb80df74e8c0d27caceb Mon Sep 17 00:00:00 2001 From: clemenso Date: Wed, 18 Mar 2009 22:27:28 +0000 Subject: 1.1-rc5 (pinProviderFactories, gui refactoring, signatureCard, secureViewer) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@322 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 352 +++++++++++++++++++-- 1 file changed, 322 insertions(+), 30 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 39952bb9..6587aaf9 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -33,12 +33,12 @@ 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 java.util.logging.Level; -import java.util.logging.Logger; import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; @@ -54,6 +54,14 @@ public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); + static final short GET_FEATURE_REQUEST = 3400; + + private static int getCtrlCode(short function) { + return 0x310000 | ((0xFFFF & function) << 2); + } + + protected Map ifdCtrlCmds; + protected List pinSpecs = new ArrayList(); private ResourceBundle i18n; @@ -106,11 +114,14 @@ public abstract class AbstractSignatureCard implements SignatureCard { */ protected byte[] selectFileAID(byte[] dfName) throws CardException, SignatureCardException { CardChannel channel = getCardChannel(); - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xA4, 0x04, - 0x00, dfName, 256)); + ResponseAPDU resp = transmit(channel, + new CommandAPDU(0x00, 0xA4, 0x04, 0x00, dfName, 256)); +// new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, dfName)); if (resp.getSW() != 0x9000) { - throw new SignatureCardException("Failed to select application AID=" - + toString(dfName) + ": SW=" + Integer.toHexString(resp.getSW()) + "."); + String msg = "Failed to select application AID=" + SMCCHelper.toString(dfName) + + ": SW=" + Integer.toHexString(resp.getSW()); + log.error(msg); + throw new SignatureCardException(msg); } else { return resp.getBytes(); } @@ -119,10 +130,63 @@ public abstract class AbstractSignatureCard implements SignatureCard { protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, SignatureCardException; - protected abstract int verifyPIN(String pin, byte kid) + /** + * VERIFY APDU without PIN BLOCK + * Not supported by ACOS cards (and GemPC Pinpad?) + * @param kid + * @return the number of possible tries until card is blocked or -1 if unknown + * (ACOS does not support this VERIFY APDU type) + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + protected abstract int verifyPIN(byte kid) throws LockedException, NotActivatedException, SignatureCardException; - + /** + * VERIFY APDU with PIN BLOCK + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin to be encoded in the PIN BLOCK + * @return -1 if VERIFY PIN was successful, or the number of possible retries + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + protected abstract int verifyPIN(byte kid, char[] pin) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException; + + /** + * CHANGE(?) APDU + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin + * @throws at.gv.egiz.smcc.SignatureCardException if activation fails + */ + protected abstract void activatePIN(byte kid, char[] pin) + throws CancelledException, TimeoutException, SignatureCardException; + + /** + * CHANGE(?) APDU + * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. + * @param kid + * @param pin + * @return -1 if CHANGE PIN was successful, or the number of possible retries + * @throws at.gv.egiz.smcc.SignatureCardException if change fails + */ + protected abstract int changePIN(byte kid, char[] oldPin, char[] newPin) + throws CancelledException, TimeoutException, SignatureCardException; + + /** + * encode the pin as needed in VERIFY/CHANGE APDUs + * @param pin + * @return + * @throws at.gv.egiz.smcc.SignatureCardException if the provided pin does + * not meet the restrictions imposed by the encoding (not the pinSpec!), + * such as maximum Length + */ + protected abstract byte[] encodePINBlock(char[] pin) throws SignatureCardException; + protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { return readRecord(getCardChannel(), recordNumber); } @@ -295,7 +359,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws SignatureCardException * @throws CardException */ - protected byte[] readTLVFile(byte[] aid, byte[] ef, String pin, byte kid, int maxLength) + protected byte[] readTLVFile(byte[] aid, byte[] ef, char[] pin, byte kid, int maxLength) throws SignatureCardException, InterruptedException, CardException { @@ -318,7 +382,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { // VERIFY if (pin != null) { - int retries = verifyPIN(pin, kid); + int retries = verifyPIN(kid, pin); if (retries != -1) { throw new VerificationFailedException(retries); } @@ -388,6 +452,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { ifs_ = 0xFF & atr.getBytes()[6]; log.trace("Setting IFS (information field size) to " + ifs_); } + ifdCtrlCmds = queryIFDFeatures(); } @Override @@ -446,39 +511,266 @@ public abstract class AbstractSignatureCard implements SignatureCard { } @Override - public int verifyPIN(PINSpec pinSpec, String pin) throws LockedException, NotActivatedException, SignatureCardException { - - Card icc = getCard(); + public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { try { - icc.beginExclusive(); - CardChannel channel = icc.getBasicChannel(); + getCard().beginExclusive(); if (pinSpec.getContextAID() != null) { - ResponseAPDU responseAPDU = transmit(channel, - new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, pinSpec.getContextAID())); - if (responseAPDU.getSW() != 0x9000) { - icc.endExclusive(); - String msg = "Failed to verify PIN " + - SMCCHelper.toString(new byte[]{pinSpec.getKID()}) + - ": Failed to verify AID " + - SMCCHelper.toString(pinSpec.getContextAID()) + - ": " + SMCCHelper.toString(responseAPDU.getBytes()); - log.error(msg); - throw new SignatureCardException(msg); - } + selectFileAID(pinSpec.getContextAID()); } - return verifyPIN(pin, pinSpec.getKID()); + + int retries = verifyPIN(pinSpec.getKID()); + do { + char[] pin = pinProvider.providePIN(pinSpec, retries); + retries = verifyPIN(pinSpec.getKID(), pin); + } while (retries > 0); + //return on -1, 0 never reached: verifyPIN throws LockedEx } catch (CardException ex) { - log.error("failed to verify pinspec: " + ex.getMessage(), ex); + log.error("failed to verify " + pinSpec.getLocalizedName() + + ": " + ex.getMessage(), ex); throw new SignatureCardException(ex); } finally { try { - icc.endExclusive(); + getCard().endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); + } + } + } + + @Override + public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) + throws CancelledException, SignatureCardException, CancelledException, TimeoutException, InterruptedException { + try { + getCard().beginExclusive(); + + if (pinSpec.getContextAID() != null) { + selectFileAID(pinSpec.getContextAID()); + } + char[] pin = pinProvider.providePIN(pinSpec, -1); + activatePIN(pinSpec.getKID(), pin); + + } catch (CardException ex) { + log.error("Failed to activate " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } finally { + try { + getCard().endExclusive(); } catch (CardException ex) { log.trace("failed to end exclusive card access: " + ex.getMessage()); } + } + } + + /** + * activates pin (newPIN) if not active + * @param pinSpec + * @param oldPIN + * @param newPIN + * @throws at.gv.egiz.smcc.LockedException + * @throws at.gv.egiz.smcc.VerificationFailedException + * @throws at.gv.egiz.smcc.NotActivatedException + * @throws at.gv.egiz.smcc.SignatureCardException + */ + @Override + public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) + throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { + try { + getCard().beginExclusive(); + + if (pinSpec.getContextAID() != null) { + selectFileAID(pinSpec.getContextAID()); + } + + int retries = verifyPIN(pinSpec.getKID()); + do { + char[] newPin = pinProvider.providePIN(pinSpec, retries); + char[] oldPin = pinProvider.provideOldPIN(pinSpec, retries); + retries = changePIN(pinSpec.getKID(), oldPin, newPin); + } while (retries > 0); + //return on -1, 0 never reached: verifyPIN throws LockedEx + } catch (CardException ex) { + log.error("Failed to change " + pinSpec.getLocalizedName() + + ": " + ex.getMessage()); + throw new SignatureCardException(ex.getMessage(), ex); + } finally { + try { + getCard().endExclusive(); + } catch (CardException ex) { + log.trace("failed to end exclusive card access: " + ex.getMessage()); + } } } + + @Override + public void unblockPIN(PINSpec pinSpec, PINProvider pinProvider) + throws CancelledException, SignatureCardException, InterruptedException { + throw new SignatureCardException("Unblock not supported yet"); + } + + ///////////////////////////////////////////////////////////////////////////// + // IFD related code + ///////////////////////////////////////////////////////////////////////////// + + /** + * TODO implement VERIFY_PIN_START/FINISH (feature 0x01/0x02) + * @return + */ + @Override + public boolean ifdSupportsFeature(byte feature) { + if (ifdCtrlCmds != null) { + return ifdCtrlCmds.containsKey(feature); + } + return false; + } + + protected Map queryIFDFeatures() { + + if (card_ == null) { + throw new NullPointerException("Need connected smart card to query IFD features"); + } + + Map ifdFeatures = new HashMap(); + + try { + if (log.isTraceEnabled()) { + log.trace("GET_FEATURE_REQUEST CtrlCode " + Integer.toHexString(getCtrlCode(GET_FEATURE_REQUEST))); + } + byte[] resp = card_.transmitControlCommand(getCtrlCode(GET_FEATURE_REQUEST), new byte[]{}); + + if (log.isTraceEnabled()) { + log.trace("GET_FEATURE_REQUEST Response " + SMCCHelper.toString(resp)); + } + + for (int i = 0; i + 5 < resp.length; i += 6) { + Byte feature = new Byte(resp[i]); + Long ctrlCode = new Long( + ((0xFF & resp[i + 2]) << 24) | + ((0xFF & resp[i + 3]) << 16) | + ((0xFF & resp[i + 4]) << 8) | + (0xFF & resp[i + 5])); + if (log.isInfoEnabled()) { + log.info("IFD supports feature " + Integer.toHexString(feature.byteValue()) + + ": " + Long.toHexString(ctrlCode.longValue())); + } + ifdFeatures.put(feature, ctrlCode); + } + + } catch (CardException ex) { + log.debug("Failed to query IFD features: " + ex.getMessage()); + log.trace(ex); + log.info("IFD does not support PINPad"); + return null; + } + return ifdFeatures; + } + + + protected byte ifdGetKeyPressed() throws CardException { + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + + Long controlCode = (Long) ifdCtrlCmds.get(new Byte((byte) 0x05)); + + byte key = 0x00; + while (key == 0x00) { + + byte[] resp = card_.transmitControlCommand(controlCode.intValue(), new byte[] {}); + + if (resp != null && resp.length > 0) { + key = resp[0]; + } + } + + System.out.println("Key: " + key); + + } + + return 0x00; + } + + protected byte[] ifdVerifyPINFinish() throws CardException { + if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { + + Long controlCode = (Long) ifdCtrlCmds.get(new Byte((byte) 0x02)); + + byte[] resp = card_.transmitControlCommand(controlCode.intValue(), new byte[] {}); + + System.out.println("CommandResp: " + toString(resp)); + + return resp; + + } + + return null; + } + + + /** + * assumes ifdSupportsVerifyPIN() == true + * @param pinVerifyStructure + * @return + * @throws javax.smartcardio.CardException + */ +// protected byte[] ifdVerifyPIN(byte[] pinVerifyStructure) throws CardException { +// +//// Long ctrlCode = (Long) ifdFeatures.get(FEATURE_IFD_PIN_PROPERTIES); +//// if (ctrlCode != null) { +//// if (log.isTraceEnabled()) { +//// log.trace("PIN_PROPERTIES CtrlCode " + Integer.toHexString(ctrlCode.intValue())); +//// } +//// byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), new byte[] {}); +//// +//// if (log.isTraceEnabled()) { +//// log.trace("PIN_PROPERTIES Response " + SMCCHelper.toString(resp)); +//// } +//// } +// +// +// Long ctrlCode = (Long) ifdFeatures.get(FEATURE_VERIFY_PIN_DIRECT); +// if (ctrlCode == null) { +// throw new NullPointerException("no CtrlCode for FEATURE_VERIFY_PIN_DIRECT"); +// } +// +// if (log.isTraceEnabled()) { +// log.trace("VERIFY_PIN_DIRECT CtrlCode " + Integer.toHexString(ctrlCode.intValue()) + +// ", PIN_VERIFY_STRUCTURE " + SMCCHelper.toString(pinVerifyStructure)); +// } +// byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), pinVerifyStructure); +// +// if (log.isTraceEnabled()) { +// log.trace("VERIFY_PIN_DIRECT Response " + SMCCHelper.toString(resp)); +// } +// return resp; +// } + +// protected Long getControlCode(Byte feature) { +// if (ifdFeatures != null) { +// return ifdFeatures.get(feature); +// } +// return null; +// } + + protected byte[] transmitControlCommand(Long ctrlCode, byte[] ctrlCommand) + throws CardException { +// Long ctrlCode = (Long) ifdFeatures.get(feature); + if (ctrlCode == null) { + throw new NullPointerException("ControlCode " + + Integer.toHexString(ctrlCode.intValue()) + " not supported"); + } + if (log.isTraceEnabled()) { + log.trace("CtrlCommand (" + Integer.toHexString(ctrlCode.intValue()) + + ") " + SMCCHelper.toString(ctrlCommand)); + } + byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), ctrlCommand); + + if (log.isTraceEnabled()) { + log.trace("CtrlCommand Response " + SMCCHelper.toString(resp)); + } + return resp; + } + } -- cgit v1.2.3 From 616e06910051528674165319a1d6d161dff5859c Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 27 Mar 2009 17:33:11 +0000 Subject: 1.1-RC6 (pinpad, pinmgmt, secureviewer) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@323 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 220 ++++----------------- 1 file changed, 38 insertions(+), 182 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 6587aaf9..47c27369 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -28,6 +28,9 @@ // package at.gv.egiz.smcc; +import at.gv.egiz.smcc.ccid.CCID; +import at.gv.egiz.smcc.ccid.DefaultReader; +import at.gv.egiz.smcc.ccid.ReaderFactory; import at.gv.egiz.smcc.util.SMCCHelper; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -39,6 +42,8 @@ import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; @@ -54,14 +59,6 @@ public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); - static final short GET_FEATURE_REQUEST = 3400; - - private static int getCtrlCode(short function) { - return 0x310000 | ((0xFFFF & function) << 2); - } - - protected Map ifdCtrlCmds; - protected List pinSpecs = new ArrayList(); private ResourceBundle i18n; @@ -76,7 +73,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { /** * The card terminal that connects the {@link #card_}. */ - private CardTerminal cardTerminal; +// private CardTerminal cardTerminal; + protected CCID reader; protected AbstractSignatureCard(String resourceBundleName) { this.resourceBundleName = resourceBundleName; @@ -341,16 +339,34 @@ public abstract class AbstractSignatureCard implements SignatureCard { */ protected byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) throws SignatureCardException, InterruptedException, CardException { - return readTLVFile(aid, ef, null, (byte) 0, maxLength); + // SELECT FILE (AID) + selectFileAID(aid); + + // SELECT FILE (EF) + ResponseAPDU resp = selectFileFID(ef); + if (resp.getSW() == 0x6a82) { + // EF not found + throw new FileNotFoundException("EF " + toString(ef) + " not found."); + } else if (resp.getSW() != 0x9000) { + throw new SignatureCardException("SELECT FILE with " + + "FID=" + + toString(ef) + + " failed (" + + "SW=" + + Integer.toHexString(resp.getSW()) + ")."); + } + + return readBinaryTLV(maxLength, (byte) 0x30); +// return readTLVFile(aid, ef, null, (byte) 0, maxLength); } /** - * Read the content of a TLV file wich may require a PIN. + * Read the content of a TLV file wich requires a PIN. * * @param aid the application ID (AID) * @param ef the elementary file (EF) * @param kid the key ID (KID) of the corresponding PIN - * @param provider the PINProvider + * @param pin the pin or null if VERIFY on pinpad * @param spec the PINSpec * @param maxLength the maximum length of the file * @@ -381,12 +397,10 @@ public abstract class AbstractSignatureCard implements SignatureCard { } // VERIFY - if (pin != null) { int retries = verifyPIN(kid, pin); if (retries != -1) { throw new VerificationFailedException(retries); } - } return readBinaryTLV(maxLength, (byte) 0x30); @@ -443,16 +457,16 @@ public abstract class AbstractSignatureCard implements SignatureCard { } + @Override public void init(Card card, CardTerminal cardTerminal) { - card_ = card; - this.cardTerminal = cardTerminal; + this.card_ = card; + this.reader = ReaderFactory.getReader(card, cardTerminal); ATR atr = card.getATR(); byte[] atrBytes = atr.getBytes(); if (atrBytes.length >= 6) { ifs_ = 0xFF & atr.getBytes()[6]; log.trace("Setting IFS (information field size) to " + ifs_); } - ifdCtrlCmds = queryIFDFeatures(); } @Override @@ -464,6 +478,11 @@ public abstract class AbstractSignatureCard implements SignatureCard { return card_.getBasicChannel(); } + @Override + public CCID getReader() { + return reader; + } + @Override public void setLocale(Locale locale) { if (locale == null) { @@ -497,9 +516,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { log.debug("Disconnect and reset smart card."); card_.disconnect(true); log.debug("Reconnect smart card."); - if (cardTerminal != null) { - card_ = cardTerminal.connect("*"); - } + card_ = reader.connect(); } catch (CardException e) { throw new SignatureCardException("Failed to reset card.", e); } @@ -520,6 +537,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { selectFileAID(pinSpec.getContextAID()); } + // -1 if ok or unknown int retries = verifyPIN(pinSpec.getKID()); do { char[] pin = pinProvider.providePIN(pinSpec, retries); @@ -611,166 +629,4 @@ public abstract class AbstractSignatureCard implements SignatureCard { throws CancelledException, SignatureCardException, InterruptedException { throw new SignatureCardException("Unblock not supported yet"); } - - ///////////////////////////////////////////////////////////////////////////// - // IFD related code - ///////////////////////////////////////////////////////////////////////////// - - /** - * TODO implement VERIFY_PIN_START/FINISH (feature 0x01/0x02) - * @return - */ - @Override - public boolean ifdSupportsFeature(byte feature) { - if (ifdCtrlCmds != null) { - return ifdCtrlCmds.containsKey(feature); - } - return false; - } - - protected Map queryIFDFeatures() { - - if (card_ == null) { - throw new NullPointerException("Need connected smart card to query IFD features"); - } - - Map ifdFeatures = new HashMap(); - - try { - if (log.isTraceEnabled()) { - log.trace("GET_FEATURE_REQUEST CtrlCode " + Integer.toHexString(getCtrlCode(GET_FEATURE_REQUEST))); - } - byte[] resp = card_.transmitControlCommand(getCtrlCode(GET_FEATURE_REQUEST), new byte[]{}); - - if (log.isTraceEnabled()) { - log.trace("GET_FEATURE_REQUEST Response " + SMCCHelper.toString(resp)); - } - - for (int i = 0; i + 5 < resp.length; i += 6) { - Byte feature = new Byte(resp[i]); - Long ctrlCode = new Long( - ((0xFF & resp[i + 2]) << 24) | - ((0xFF & resp[i + 3]) << 16) | - ((0xFF & resp[i + 4]) << 8) | - (0xFF & resp[i + 5])); - if (log.isInfoEnabled()) { - log.info("IFD supports feature " + Integer.toHexString(feature.byteValue()) + - ": " + Long.toHexString(ctrlCode.longValue())); - } - ifdFeatures.put(feature, ctrlCode); - } - - } catch (CardException ex) { - log.debug("Failed to query IFD features: " + ex.getMessage()); - log.trace(ex); - log.info("IFD does not support PINPad"); - return null; - } - return ifdFeatures; - } - - - protected byte ifdGetKeyPressed() throws CardException { - if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { - - Long controlCode = (Long) ifdCtrlCmds.get(new Byte((byte) 0x05)); - - byte key = 0x00; - while (key == 0x00) { - - byte[] resp = card_.transmitControlCommand(controlCode.intValue(), new byte[] {}); - - if (resp != null && resp.length > 0) { - key = resp[0]; - } - } - - System.out.println("Key: " + key); - - } - - return 0x00; - } - - protected byte[] ifdVerifyPINFinish() throws CardException { - if (ifdSupportsFeature(FEATURE_VERIFY_PIN_DIRECT)) { - - Long controlCode = (Long) ifdCtrlCmds.get(new Byte((byte) 0x02)); - - byte[] resp = card_.transmitControlCommand(controlCode.intValue(), new byte[] {}); - - System.out.println("CommandResp: " + toString(resp)); - - return resp; - - } - - return null; - } - - - /** - * assumes ifdSupportsVerifyPIN() == true - * @param pinVerifyStructure - * @return - * @throws javax.smartcardio.CardException - */ -// protected byte[] ifdVerifyPIN(byte[] pinVerifyStructure) throws CardException { -// -//// Long ctrlCode = (Long) ifdFeatures.get(FEATURE_IFD_PIN_PROPERTIES); -//// if (ctrlCode != null) { -//// if (log.isTraceEnabled()) { -//// log.trace("PIN_PROPERTIES CtrlCode " + Integer.toHexString(ctrlCode.intValue())); -//// } -//// byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), new byte[] {}); -//// -//// if (log.isTraceEnabled()) { -//// log.trace("PIN_PROPERTIES Response " + SMCCHelper.toString(resp)); -//// } -//// } -// -// -// Long ctrlCode = (Long) ifdFeatures.get(FEATURE_VERIFY_PIN_DIRECT); -// if (ctrlCode == null) { -// throw new NullPointerException("no CtrlCode for FEATURE_VERIFY_PIN_DIRECT"); -// } -// -// if (log.isTraceEnabled()) { -// log.trace("VERIFY_PIN_DIRECT CtrlCode " + Integer.toHexString(ctrlCode.intValue()) + -// ", PIN_VERIFY_STRUCTURE " + SMCCHelper.toString(pinVerifyStructure)); -// } -// byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), pinVerifyStructure); -// -// if (log.isTraceEnabled()) { -// log.trace("VERIFY_PIN_DIRECT Response " + SMCCHelper.toString(resp)); -// } -// return resp; -// } - -// protected Long getControlCode(Byte feature) { -// if (ifdFeatures != null) { -// return ifdFeatures.get(feature); -// } -// return null; -// } - - protected byte[] transmitControlCommand(Long ctrlCode, byte[] ctrlCommand) - throws CardException { -// Long ctrlCode = (Long) ifdFeatures.get(feature); - if (ctrlCode == null) { - throw new NullPointerException("ControlCode " + - Integer.toHexString(ctrlCode.intValue()) + " not supported"); - } - if (log.isTraceEnabled()) { - log.trace("CtrlCommand (" + Integer.toHexString(ctrlCode.intValue()) + - ") " + SMCCHelper.toString(ctrlCommand)); - } - byte[] resp = card_.transmitControlCommand(ctrlCode.intValue(), ctrlCommand); - - if (log.isTraceEnabled()) { - log.trace("CtrlCommand Response " + SMCCHelper.toString(resp)); - } - return resp; - } - } -- cgit v1.2.3 From 2dbf2347bc78fd835c857ad438514fb6251f6f7a Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 2 Apr 2009 19:13:48 +0000 Subject: 1.1-RC7 (pinpad revisited) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@325 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/smcc/AbstractSignatureCard.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 47c27369..7dd3ee78 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -29,21 +29,16 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.ccid.DefaultReader; import at.gv.egiz.smcc.ccid.ReaderFactory; 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 java.util.logging.Level; -import java.util.logging.Logger; import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; @@ -152,8 +147,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws at.gv.egiz.smcc.SignatureCardException */ protected abstract int verifyPIN(byte kid, char[] pin) - throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException; - + throws LockedException, NotActivatedException, CancelledException, PINFormatException, TimeoutException, PINOperationAbortedException, SignatureCardException; + /** * CHANGE(?) APDU * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. @@ -162,7 +157,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws at.gv.egiz.smcc.SignatureCardException if activation fails */ protected abstract void activatePIN(byte kid, char[] pin) - throws CancelledException, TimeoutException, SignatureCardException; + throws CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException; /** * CHANGE(?) APDU @@ -173,7 +168,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { * @throws at.gv.egiz.smcc.SignatureCardException if change fails */ protected abstract int changePIN(byte kid, char[] oldPin, char[] newPin) - throws CancelledException, TimeoutException, SignatureCardException; + throws LockedException, NotActivatedException, CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException; /** * encode the pin as needed in VERIFY/CHANGE APDUs @@ -595,7 +590,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { */ @Override public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) - throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { + throws LockedException, NotActivatedException, CancelledException, + TimeoutException, SignatureCardException, InterruptedException { try { getCard().beginExclusive(); -- cgit v1.2.3 From e75f30d8d51fa33fc778c31c1b0312cf10de8e45 Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 25 Jun 2009 17:01:14 +0000 Subject: disable pinpad git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@376 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 7dd3ee78..f0f8b8c8 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -455,7 +455,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { @Override public void init(Card card, CardTerminal cardTerminal) { this.card_ = card; - this.reader = ReaderFactory.getReader(card, cardTerminal); + this.reader = ReaderFactory.getInstance().getReader(card, cardTerminal); ATR atr = card.getATR(); byte[] atrBytes = atr.getBytes(); if (atrBytes.length >= 6) { -- cgit v1.2.3 From 6cb4a071eab9a3b8cf78b8ec7e407aa148f2d038 Mon Sep 17 00:00:00 2001 From: mcentner Date: Wed, 1 Jul 2009 13:03:41 +0000 Subject: Major refactoring of SMCC git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@381 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/smcc/AbstractSignatureCard.java | 541 +-------------------- 1 file changed, 20 insertions(+), 521 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 f0f8b8c8..54b4c7fe 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -1,55 +1,37 @@ -//Copyright (C) 2002 IAIK -//http://jce.iaik.at -// -//Copyright (C) 2003 Stiftung Secure Information and -// Communication Technologies SIC -//http://www.sic.st -// -//All rights reserved. -// -//This source is provided for inspection purposes and recompilation only, -//unless specified differently in a contract with IAIK. This source has to -//be kept in strict confidence and must not be disclosed to any third party -//under any circumstances. Redistribution in source and binary forms, with -//or without modification, are permitted in any case! -// -//THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -//SUCH DAMAGE. -// -// +/* +* 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 at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.ccid.ReaderFactory; -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.List; import java.util.Locale; import java.util.ResourceBundle; -import javax.smartcardio.ATR; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; -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.ccid.CCID; +import at.gv.egiz.smcc.ccid.ReaderFactory; + public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); @@ -61,14 +43,8 @@ public abstract class AbstractSignatureCard implements SignatureCard { private Locale locale = Locale.getDefault(); - int ifs_ = 254; - private Card card_; - /** - * The card terminal that connects the {@link #card_}. - */ -// private CardTerminal cardTerminal; protected CCID reader; protected AbstractSignatureCard(String resourceBundleName) { @@ -89,379 +65,10 @@ public abstract class AbstractSignatureCard implements SignatureCard { return sb.toString(); } - /** - * Select an application using AID as DF name according to ISO/IEC 7816-4 - * section 8.2.2.2. - * - * @param dfName - * AID of the application to be selected - * - * @return the response data of the response APDU if SW=0x9000 - * - * @throws CardException - * if card communication fails - * - * @throws SignatureCardException - * if application selection fails (e.g. an application with the - * given AID is not present on the card) - */ - protected byte[] selectFileAID(byte[] dfName) throws CardException, SignatureCardException { - CardChannel channel = getCardChannel(); - ResponseAPDU resp = transmit(channel, - new CommandAPDU(0x00, 0xA4, 0x04, 0x00, dfName, 256)); -// new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, dfName)); - if (resp.getSW() != 0x9000) { - String msg = "Failed to select application AID=" + SMCCHelper.toString(dfName) + - ": SW=" + Integer.toHexString(resp.getSW()); - log.error(msg); - throw new SignatureCardException(msg); - } else { - return resp.getBytes(); - } - } - - protected abstract ResponseAPDU selectFileFID(byte[] fid) throws CardException, - SignatureCardException; - - /** - * VERIFY APDU without PIN BLOCK - * Not supported by ACOS cards (and GemPC Pinpad?) - * @param kid - * @return the number of possible tries until card is blocked or -1 if unknown - * (ACOS does not support this VERIFY APDU type) - * @throws at.gv.egiz.smcc.LockedException - * @throws at.gv.egiz.smcc.NotActivatedException - * @throws at.gv.egiz.smcc.SignatureCardException - */ - protected abstract int verifyPIN(byte kid) - throws LockedException, NotActivatedException, SignatureCardException; - - /** - * VERIFY APDU with PIN BLOCK - * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. - * @param kid - * @param pin to be encoded in the PIN BLOCK - * @return -1 if VERIFY PIN was successful, or the number of possible retries - * @throws at.gv.egiz.smcc.LockedException - * @throws at.gv.egiz.smcc.NotActivatedException - * @throws at.gv.egiz.smcc.SignatureCardException - */ - protected abstract int verifyPIN(byte kid, char[] pin) - throws LockedException, NotActivatedException, CancelledException, PINFormatException, TimeoutException, PINOperationAbortedException, SignatureCardException; - - /** - * CHANGE(?) APDU - * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. - * @param kid - * @param pin - * @throws at.gv.egiz.smcc.SignatureCardException if activation fails - */ - protected abstract void activatePIN(byte kid, char[] pin) - throws CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException; - - /** - * CHANGE(?) APDU - * If IFD supports VERIFY_PIN on pinpad, parameter pin may be empty. - * @param kid - * @param pin - * @return -1 if CHANGE PIN was successful, or the number of possible retries - * @throws at.gv.egiz.smcc.SignatureCardException if change fails - */ - protected abstract int changePIN(byte kid, char[] oldPin, char[] newPin) - throws LockedException, NotActivatedException, CancelledException, PINFormatException, PINConfirmationException, TimeoutException, PINOperationAbortedException, SignatureCardException; - - /** - * encode the pin as needed in VERIFY/CHANGE APDUs - * @param pin - * @return - * @throws at.gv.egiz.smcc.SignatureCardException if the provided pin does - * not meet the restrictions imposed by the encoding (not the pinSpec!), - * such as maximum Length - */ - protected abstract byte[] encodePINBlock(char[] pin) throws SignatureCardException; - - protected byte[] readRecord(int recordNumber) throws SignatureCardException, CardException { - return readRecord(getCardChannel(), recordNumber); - } - - protected byte[] readRecord(CardChannel channel, int recordNumber) throws SignatureCardException, CardException { - - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB2, - recordNumber, 0x04, 256)); - if (resp.getSW() == 0x9000) { - return resp.getData(); - } else { - throw new SignatureCardException("Failed to read records. SW=" + Integer.toHexString(resp.getSW())); - } - - } - - protected byte[] readBinary(CardChannel channel, int offset, int len) - throws CardException, SignatureCardException { - - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB0, - 0x7F & (offset >> 8), offset & 0xFF, len)); - if (resp.getSW() == 0x9000) { - return resp.getData(); - } else if (resp.getSW() == 0x6982) { - throw new SecurityStatusNotSatisfiedException(); - } else { - throw new SignatureCardException("Failed to read bytes (" + offset + "+" - + len + "): SW=" + Integer.toHexString(resp.getSW())); - } - - } - - protected int readBinary(int offset, int len, byte[] b) throws CardException, - SignatureCardException { - - if (b.length < len) { - throw new IllegalArgumentException( - "Length of b must not be less than len."); - } - - CardChannel channel = getCardChannel(); - - ResponseAPDU resp = transmit(channel, new CommandAPDU(0x00, 0xB0, - 0x7F & (offset >> 8), offset & 0xFF, len)); - if (resp.getSW() == 0x9000) { - System.arraycopy(resp.getData(), 0, b, 0, len); - } - - return resp.getSW(); - - } - - protected byte[] readBinaryTLV(int maxSize, byte expectedType) throws CardException, - SignatureCardException { - - CardChannel channel = getCardChannel(); - - // read first chunk - int len = Math.min(maxSize, ifs_); - byte[] chunk = readBinary(channel, 0, len); - if (chunk.length > 0 && chunk[0] != expectedType) { - return null; - } - int offset = chunk.length; - int actualSize = maxSize; - if (chunk.length > 3) { - if ((chunk[1] & 0x80) > 0) { - int octets = (0x0F & chunk[1]); - actualSize = 2 + octets; - for (int i = 1; i <= octets; i++) { - actualSize += (0xFF & chunk[i + 1]) << ((octets - i) * 8); - } - } else { - actualSize = 2 + chunk[1]; - } - } - ByteBuffer buffer = ByteBuffer.allocate(actualSize); - buffer.put(chunk, 0, Math.min(actualSize, chunk.length)); - while (offset < actualSize) { - len = Math.min(ifs_, actualSize - offset); - chunk = readBinary(channel, offset, len); - buffer.put(chunk); - offset += chunk.length; - } - return buffer.array(); - - } - - protected byte[] readRecords(byte[] aid, byte[] ef, int start, int end) throws SignatureCardException, InterruptedException { - - try { - - // SELECT FILE (AID) - byte[] rb = selectFileAID(aid); - if (rb[rb.length - 2] != (byte) 0x90 || rb[rb.length - 1] != (byte) 0x00) { - - throw new SignatureCardException("SELECT FILE with " - + "AID=" - + toString(aid) - + " failed (" - + "SW=" - + Integer.toHexString((0xFF & (int) rb[rb.length - 1]) - | (0xFF & (int) rb[rb.length - 2]) << 8) + ")."); - - } - - // SELECT FILE (EF) - ResponseAPDU resp = selectFileFID(ef); - if (resp.getSW() == 0x6a82) { - - // EF not found - throw new FileNotFoundException("EF " + toString(ef) + " not found."); - - } else if (resp.getSW() != 0x9000) { - - throw new SignatureCardException("SELECT FILE with " - + "FID=" - + toString(ef) - + " failed (" - + "SW=" - + Integer.toHexString(resp.getSW()) + ")."); - - } - - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - - for (int i = start; i <= end; i++) { - bytes.write(readRecord(i)); - } - - return bytes.toByteArray(); - - } catch (CardException e) { - throw new SignatureCardException("Failed to acces card.", e); - } catch (IOException e) { - throw new SignatureCardException("Failed to read records.", e); - } - - } - - /** - * Read the content of a TLV file. - * - * @param aid the application ID (AID) - * @param ef the elementary file (EF) - * @param maxLength the maximum length of the file - * - * @return the content of the file - * - * @throws SignatureCardException - * @throws CardException - */ - protected byte[] readTLVFile(byte[] aid, byte[] ef, int maxLength) - throws SignatureCardException, InterruptedException, CardException { - // SELECT FILE (AID) - selectFileAID(aid); - - // SELECT FILE (EF) - ResponseAPDU resp = selectFileFID(ef); - if (resp.getSW() == 0x6a82) { - // EF not found - throw new FileNotFoundException("EF " + toString(ef) + " not found."); - } else if (resp.getSW() != 0x9000) { - throw new SignatureCardException("SELECT FILE with " - + "FID=" - + toString(ef) - + " failed (" - + "SW=" - + Integer.toHexString(resp.getSW()) + ")."); - } - - return readBinaryTLV(maxLength, (byte) 0x30); -// return readTLVFile(aid, ef, null, (byte) 0, maxLength); - } - - /** - * Read the content of a TLV file wich requires a PIN. - * - * @param aid the application ID (AID) - * @param ef the elementary file (EF) - * @param kid the key ID (KID) of the corresponding PIN - * @param pin the pin or null if VERIFY on pinpad - * @param spec the PINSpec - * @param maxLength the maximum length of the file - * - * @return the content of the file - * - * @throws SignatureCardException - * @throws CardException - */ - protected byte[] readTLVFile(byte[] aid, byte[] ef, char[] pin, byte kid, int maxLength) - throws SignatureCardException, InterruptedException, CardException { - - - // SELECT FILE (AID) - selectFileAID(aid); - - // SELECT FILE (EF) - ResponseAPDU resp = selectFileFID(ef); - if (resp.getSW() == 0x6a82) { - // EF not found - throw new FileNotFoundException("EF " + toString(ef) + " not found."); - } else if (resp.getSW() != 0x9000) { - throw new SignatureCardException("SELECT FILE with " - + "FID=" - + toString(ef) - + " failed (" - + "SW=" - + Integer.toHexString(resp.getSW()) + ")."); - } - - // VERIFY - int retries = verifyPIN(kid, pin); - if (retries != -1) { - throw new VerificationFailedException(retries); - } - - return readBinaryTLV(maxLength, (byte) 0x30); - - - } - - /** - * Transmit the given command APDU using the given card channel. - * - * @param channel - * the card channel - * @param commandAPDU - * the command APDU - * @param logData - * true if command APDU data may be logged, or - * false otherwise - * - * @return the corresponding response APDU - * - * @throws CardException - * if smart card communication fails - */ - protected ResponseAPDU transmit(CardChannel channel, CommandAPDU commandAPDU, boolean logData) - throws CardException { - - if (log.isTraceEnabled()) { - log.trace(commandAPDU - + (logData ? "\n" + toString(commandAPDU.getBytes()) : "")); - long t0 = System.currentTimeMillis(); - ResponseAPDU responseAPDU = channel.transmit(commandAPDU); - long t1 = System.currentTimeMillis(); - log.trace(responseAPDU + "\n[" + (t1 - t0) + "ms] " - + (logData ? "\n" + toString(responseAPDU.getBytes()) : "")); - return responseAPDU; - } else { - return channel.transmit(commandAPDU); - } - - } - - /** - * Transmit the given command APDU using the given card channel. - * - * @param channel the card channel - * @param commandAPDU the command APDU - * - * @return the corresponding response APDU - * - * @throws CardException if smart card communication fails - */ - protected ResponseAPDU transmit(CardChannel channel, CommandAPDU commandAPDU) - throws CardException { - return transmit(channel, commandAPDU, true); - } - - @Override public void init(Card card, CardTerminal cardTerminal) { this.card_ = card; this.reader = ReaderFactory.getInstance().getReader(card, cardTerminal); - ATR atr = card.getATR(); - byte[] atrBytes = atr.getBytes(); - if (atrBytes.length >= 6) { - ifs_ = 0xFF & atr.getBytes()[6]; - log.trace("Setting IFS (information field size) to " + ifs_); - } } @Override @@ -470,7 +77,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { } protected CardChannel getCardChannel() { - return card_.getBasicChannel(); + return new LogCardChannel(card_.getBasicChannel()); } @Override @@ -517,112 +124,4 @@ public abstract class AbstractSignatureCard implements SignatureCard { } } - @Override - public List getPINSpecs() { - return pinSpecs; - } - - @Override - public void verifyPIN(PINSpec pinSpec, PINProvider pinProvider) - throws LockedException, NotActivatedException, CancelledException, TimeoutException, SignatureCardException, InterruptedException { - try { - getCard().beginExclusive(); - - if (pinSpec.getContextAID() != null) { - selectFileAID(pinSpec.getContextAID()); - } - - // -1 if ok or unknown - int retries = verifyPIN(pinSpec.getKID()); - do { - char[] pin = pinProvider.providePIN(pinSpec, retries); - retries = verifyPIN(pinSpec.getKID(), pin); - } while (retries > 0); - //return on -1, 0 never reached: verifyPIN throws LockedEx - - } catch (CardException ex) { - log.error("failed to verify " + pinSpec.getLocalizedName() + - ": " + ex.getMessage(), ex); - throw new SignatureCardException(ex); - } finally { - try { - getCard().endExclusive(); - } catch (CardException ex) { - log.trace("failed to end exclusive card access: " + ex.getMessage()); - } - } - } - - @Override - public void activatePIN(PINSpec pinSpec, PINProvider pinProvider) - throws CancelledException, SignatureCardException, CancelledException, TimeoutException, InterruptedException { - try { - getCard().beginExclusive(); - - if (pinSpec.getContextAID() != null) { - selectFileAID(pinSpec.getContextAID()); - } - char[] pin = pinProvider.providePIN(pinSpec, -1); - activatePIN(pinSpec.getKID(), pin); - - } catch (CardException ex) { - log.error("Failed to activate " + pinSpec.getLocalizedName() + - ": " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); - } finally { - try { - getCard().endExclusive(); - } catch (CardException ex) { - log.trace("failed to end exclusive card access: " + ex.getMessage()); - } - } - } - - /** - * activates pin (newPIN) if not active - * @param pinSpec - * @param oldPIN - * @param newPIN - * @throws at.gv.egiz.smcc.LockedException - * @throws at.gv.egiz.smcc.VerificationFailedException - * @throws at.gv.egiz.smcc.NotActivatedException - * @throws at.gv.egiz.smcc.SignatureCardException - */ - @Override - public void changePIN(PINSpec pinSpec, ChangePINProvider pinProvider) - throws LockedException, NotActivatedException, CancelledException, - TimeoutException, SignatureCardException, InterruptedException { - try { - getCard().beginExclusive(); - - if (pinSpec.getContextAID() != null) { - selectFileAID(pinSpec.getContextAID()); - } - - int retries = verifyPIN(pinSpec.getKID()); - do { - char[] newPin = pinProvider.providePIN(pinSpec, retries); - char[] oldPin = pinProvider.provideOldPIN(pinSpec, retries); - retries = changePIN(pinSpec.getKID(), oldPin, newPin); - } while (retries > 0); - //return on -1, 0 never reached: verifyPIN throws LockedEx - - } catch (CardException ex) { - log.error("Failed to change " + pinSpec.getLocalizedName() + - ": " + ex.getMessage()); - throw new SignatureCardException(ex.getMessage(), ex); - } finally { - try { - getCard().endExclusive(); - } catch (CardException ex) { - log.trace("failed to end exclusive card access: " + ex.getMessage()); - } - } - } - - @Override - public void unblockPIN(PINSpec pinSpec, PINProvider pinProvider) - throws CancelledException, SignatureCardException, InterruptedException { - throw new SignatureCardException("Unblock not supported yet"); - } } -- cgit v1.2.3 From 3da4655d011dfc2f04f9e4ac28b38aee42d01bc0 Mon Sep 17 00:00:00 2001 From: clemenso Date: Tue, 5 Jan 2010 10:06:47 +0000 Subject: Features [#437] Handle pinpad [64:03] response apdu correctly [#445] pin entry feedback for VERIFY_PIN_START/FINISH [#471] Provide SecureViewer Link before Pinpad PinEntry timeout starts Bugs [#479] PIN Managment Applet allows unmatching new pin and pin confirmation [#480] PIN Management displays blocked PINs as ACTIVE [#486] Not possible to select 3 times in series the same item from signedReferencesList for display in secureViewer [#506] change pin dialog (gui) issues [#508] e-card G3 PIN activation (with TransportPIN) not supported [#509] closing secure viewer window (WINDOW_CLOSING) leaves "signature data is displayed in viewer" dialog in applet git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@565 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/smcc/AbstractSignatureCard.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java') 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 54b4c7fe..fcb94fc6 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -16,6 +16,8 @@ */ package at.gv.egiz.smcc; +import at.gv.egiz.smcc.reader.CardReader; +import at.gv.egiz.smcc.reader.ReaderFactory; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -29,9 +31,6 @@ import javax.smartcardio.CardTerminal; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import at.gv.egiz.smcc.ccid.CCID; -import at.gv.egiz.smcc.ccid.ReaderFactory; - public abstract class AbstractSignatureCard implements SignatureCard { private static Log log = LogFactory.getLog(AbstractSignatureCard.class); @@ -45,7 +44,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { private Card card_; - protected CCID reader; + protected CardReader reader; protected AbstractSignatureCard(String resourceBundleName) { this.resourceBundleName = resourceBundleName; @@ -68,7 +67,7 @@ public abstract class AbstractSignatureCard implements SignatureCard { @Override public void init(Card card, CardTerminal cardTerminal) { this.card_ = card; - this.reader = ReaderFactory.getInstance().getReader(card, cardTerminal); + this.reader = ReaderFactory.getReader(card, cardTerminal); } @Override @@ -80,11 +79,6 @@ public abstract class AbstractSignatureCard implements SignatureCard { return new LogCardChannel(card_.getBasicChannel()); } - @Override - public CCID getReader() { - return reader; - } - @Override public void setLocale(Locale locale) { if (locale == null) { -- cgit v1.2.3