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