keep track of used cards

This commit is contained in:
Michele Balistreri 2019-01-15 17:00:01 +03:00
parent 50fa93dd32
commit 93d71ab70b
1 changed files with 32 additions and 10 deletions

View File

@ -6,6 +6,7 @@ import im.status.keycard.io.WrongPINException;
import java.io.IOException; import java.io.IOException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.HashSet;
/** /**
* Class helping with the card duplication process. Depending on the client's role, only some of the methods are relevant. * Class helping with the card duplication process. Depending on the client's role, only some of the methods are relevant.
@ -15,6 +16,10 @@ public class CardDuplicator {
private KeycardCommandSet cmdSet; private KeycardCommandSet cmdSet;
private DuplicatorCallback cb; private DuplicatorCallback cb;
private HashSet<byte[]> startedDuplication;
private HashSet<byte[]> addedEntropy;
private HashSet<byte[]> finishedDuplication;
/** /**
* Creates a CardDuplicator object. Regardless of the role of the client, this object must be kept and used for the * Creates a CardDuplicator object. Regardless of the role of the client, this object must be kept and used for the
* entire duplication session. It cannot be reused for multiple sessions. * entire duplication session. It cannot be reused for multiple sessions.
@ -26,6 +31,10 @@ public class CardDuplicator {
public CardDuplicator(KeycardCommandSet cmdSet, DuplicatorCallback cb) { public CardDuplicator(KeycardCommandSet cmdSet, DuplicatorCallback cb) {
this.cmdSet = cmdSet; this.cmdSet = cmdSet;
this.cb = cb; this.cb = cb;
this.startedDuplication = new HashSet<>();
this.addedEntropy = new HashSet<>();
this.finishedDuplication = new HashSet<>();
this.secret = new byte[32]; this.secret = new byte[32];
SecureRandom random = new SecureRandom(); SecureRandom random = new SecureRandom();
random.nextBytes(this.secret); random.nextBytes(this.secret);
@ -40,9 +49,19 @@ public class CardDuplicator {
this(new KeycardCommandSet(channel), null); this(new KeycardCommandSet(channel), null);
} }
private ApplicationInfo selectAndCheck(HashSet<byte[]> processed) throws APDUException, IOException {
private void preamble() throws IOException, APDUException {
ApplicationInfo appInfo = new ApplicationInfo(cmdSet.select().checkOK().getData()); ApplicationInfo appInfo = new ApplicationInfo(cmdSet.select().checkOK().getData());
if (!processed.add(appInfo.getInstanceUID())) {
throw new IllegalStateException("The requested action has been already performed on this card");
}
return appInfo;
}
private void preamble(HashSet<byte[]> processed) throws IOException, APDUException {
ApplicationInfo appInfo = selectAndCheck(processed);
Pairing pairing = cb.getPairing(appInfo); Pairing pairing = cb.getPairing(appInfo);
if (pairing == null) { if (pairing == null) {
@ -75,9 +94,10 @@ public class CardDuplicator {
* *
* @throws IOException communication error * @throws IOException communication error
* @throws APDUException unexpected card response * @throws APDUException unexpected card response
* @throws IllegalStateException this card has already been used
*/ */
public void startDuplication(int clientCount) throws IOException, APDUException { public void startDuplication(int clientCount) throws IOException, APDUException, IllegalStateException {
preamble(); preamble(startedDuplication);
cmdSet.duplicateKeyStart(clientCount, secret).checkOK(); cmdSet.duplicateKeyStart(clientCount, secret).checkOK();
} }
@ -87,8 +107,8 @@ public class CardDuplicator {
* @throws IOException communication error * @throws IOException communication error
* @throws APDUException unexpected card response * @throws APDUException unexpected card response
*/ */
public byte[] exportKey() throws IOException, APDUException { public byte[] exportKey() throws IOException, APDUException, IllegalStateException {
preamble(); preamble(finishedDuplication);
return cmdSet.duplicateKeyExport().checkOK().getData(); return cmdSet.duplicateKeyExport().checkOK().getData();
} }
@ -99,9 +119,10 @@ public class CardDuplicator {
* @return the key UID * @return the key UID
* @throws IOException communication error * @throws IOException communication error
* @throws APDUException unexpected card response * @throws APDUException unexpected card response
* @throws IllegalStateException this card has already been used
*/ */
public byte[] importKey(byte[] key) throws IOException, APDUException { public byte[] importKey(byte[] key) throws IOException, APDUException, IllegalStateException {
preamble(); preamble(finishedDuplication);
return cmdSet.duplicateKeyImport(key).checkOK().getData(); return cmdSet.duplicateKeyImport(key).checkOK().getData();
} }
@ -111,9 +132,10 @@ public class CardDuplicator {
* *
* @throws IOException communication error * @throws IOException communication error
* @throws APDUException unexpected card response * @throws APDUException unexpected card response
* @throws IllegalStateException this card has already been used
*/ */
public void addEntropy() throws IOException, APDUException { public void addEntropy() throws IOException, APDUException, IllegalStateException {
cmdSet.select().checkOK(); selectAndCheck(addedEntropy);
cmdSet.duplicateKeyAddEntropy(secret).checkOK(); cmdSet.duplicateKeyAddEntropy(secret).checkOK();
} }
} }