Compare commits

..
Author SHA1 Message Date
Michele Balistreri 3dfd1421f7 support export chain code 2022-11-09 19:21:51 +01:00
Michele Balistreri 9fac06b19d Add IDENTIFY CARD (#24)
* ident applet support

* add identify card command

* fix certificate class

* make sure private key is 32 bytes

* don't remove TLV header from signature

* fix typo

* use secure channel if open
2022-11-04 12:33:06 +01:00
Audrius Molis 6c965f726a test adding exception info to the RuntimeException in RuntimeException (#26) 2022-09-09 15:31:58 +02:00
3 changed files with 79 additions and 17 deletions
@@ -77,8 +77,9 @@ public class KeycardCommandSet {
static final byte EXPORT_KEY_P1_DERIVE = 0x01;
static final byte EXPORT_KEY_P1_DERIVE_AND_MAKE_CURRENT = 0x02;
static final byte EXPORT_KEY_P2_PRIVATE_AND_PUBLIC = 0x00;
static final byte EXPORT_KEY_P2_PUBLIC_ONLY = 0x01;
public static final byte EXPORT_KEY_P2_PRIVATE_AND_PUBLIC = 0x00;
public static final byte EXPORT_KEY_P2_PUBLIC_ONLY = 0x01;
public static final byte EXPORT_KEY_P2_EXTENDED_PUBLIC = 0x02;
static final byte TLV_APPLICATION_INFO_TEMPLATE = (byte) 0xA4;
@@ -633,6 +634,10 @@ public class KeycardCommandSet {
return secureChannel.transmit(apduChannel, setPinlessPath);
}
private byte poToP2(boolean publicOnly) {
return publicOnly ? EXPORT_KEY_P2_PUBLIC_ONLY : EXPORT_KEY_P2_PRIVATE_AND_PUBLIC;
}
/**
* Sends an EXPORT KEY APDU to export the current key.
*
@@ -641,9 +646,20 @@ public class KeycardCommandSet {
* @throws IOException communication error
*/
public APDUResponse exportCurrentKey(boolean publicOnly) throws IOException {
return exportKey(EXPORT_KEY_P1_CURRENT, publicOnly, new byte[0]);
return exportCurrentKey(poToP2(publicOnly));
}
/**
* Sends an EXPORT KEY APDU to export the current key.
*
* @param p2 the p2 parameter
* @return the raw card reponse
* @throws IOException communication error
*/
public APDUResponse exportCurrentKey(byte p2) throws IOException {
return exportKey(EXPORT_KEY_P1_CURRENT, p2, new byte[0]);
}
/**
* Sends an EXPORT KEY APDU. Performs derivation of the given keypath and optionally makes it the current key.
*
@@ -654,10 +670,23 @@ public class KeycardCommandSet {
* @throws IOException communication error
*/
public APDUResponse exportKey(String keyPath, boolean makeCurrent, boolean publicOnly) throws IOException {
KeyPath path = new KeyPath(keyPath);
return exportKey(path.getData(), path.getSource(), makeCurrent, publicOnly);
return exportKey(keyPath, makeCurrent, poToP2(publicOnly));
}
/**
* Sends an EXPORT KEY APDU. Performs derivation of the given keypath and optionally makes it the current key.
*
* @param keyPath the keypath to export
* @param makeCurrent if the key should be made current or not
* @param p2 the P2 parameter
* @return the raw card response
* @throws IOException communication error
*/
public APDUResponse exportKey(String keyPath, boolean makeCurrent, byte p2) throws IOException {
KeyPath path = new KeyPath(keyPath);
return exportKey(path.getData(), path.getSource(), makeCurrent, p2);
}
/**
* Sends an EXPORT KEY APDU. Performs derivation of the given keypath and optionally makes it the current key.
*
@@ -668,10 +697,23 @@ public class KeycardCommandSet {
* @throws IOException communication error
*/
public APDUResponse exportKey(byte[] keyPath, int source, boolean makeCurrent, boolean publicOnly) throws IOException {
int p1 = source | (makeCurrent ? EXPORT_KEY_P1_DERIVE_AND_MAKE_CURRENT : EXPORT_KEY_P1_DERIVE);
return exportKey(p1, publicOnly, keyPath);
return exportKey(keyPath, source, makeCurrent, poToP2(publicOnly));
}
/**
* Sends an EXPORT KEY APDU. Performs derivation of the given keypath and optionally makes it the current key.
*
* @param keyPath the keypath to export
* @param makeCurrent if the key should be made current or not
* @param p2 the P2 parameter
* @return the raw card response
* @throws IOException communication error
*/
public APDUResponse exportKey(byte[] keyPath, int source, boolean makeCurrent, byte p2) throws IOException {
int p1 = source | (makeCurrent ? EXPORT_KEY_P1_DERIVE_AND_MAKE_CURRENT : EXPORT_KEY_P1_DERIVE);
return exportKey(p1, p2, keyPath);
}
/**
* Sends an EXPORT KEY APDU. The parameters are sent as-is.
*
@@ -682,10 +724,22 @@ public class KeycardCommandSet {
* @throws IOException communication error
*/
public APDUResponse exportKey(int derivationOptions, boolean publicOnly, byte[] keypath) throws IOException {
byte p2 = publicOnly ? EXPORT_KEY_P2_PUBLIC_ONLY : EXPORT_KEY_P2_PRIVATE_AND_PUBLIC;
return exportKey(derivationOptions, poToP2(publicOnly), keypath);
}
/**
* Sends an EXPORT KEY APDU. The parameters are sent as-is.
*
* @param derivationOptions the P1 parameter
* @param p2 the P2 parameter
* @param keypath the data parameter
* @return the raw card response
* @throws IOException communication error
*/
public APDUResponse exportKey(int derivationOptions, byte p2, byte[] keypath) throws IOException {
APDUCommand exportKey = secureChannel.protectedCommand(0x80, INS_EXPORT_KEY, derivationOptions, p2, keypath);
return secureChannel.transmit(apduChannel, exportKey);
}
}
/**
* Sends a GET DATA APDU.
@@ -124,7 +124,7 @@ public class Mnemonic {
PBEKeySpec spec = new PBEKeySpec(mnemonicPhrase.toCharArray(), ("mnemonic" + password).getBytes(), 2048, 512);
key = skf.generateSecret(spec);
} catch (Exception e) {
throw new RuntimeException("Is Bouncycastle correctly initialized?");
throw new RuntimeException("Is Bouncycastle correctly initialized?", e);
}
return key.getEncoded();
@@ -278,11 +278,7 @@ public class GlobalPlatformCommandSet {
* @throws IOException communication error
*/
public void deleteKeycardInstancesAndPackage() throws IOException, APDUException {
deleteNDEFInstance().checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
deleteKeycardInstance().checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
deleteCashInstance().checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
deleteIdentInstance().checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
deleteKeycardPackage().checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
delete(Identifiers.PACKAGE_AID, (byte) 0x80).checkSW(APDUResponse.SW_OK, APDUResponse.SW_REFERENCED_DATA_NOT_FOUND);
}
/**
@@ -293,15 +289,27 @@ public class GlobalPlatformCommandSet {
* @throws IOException communication error.
*/
public APDUResponse delete(byte[] aid) throws IOException {
return delete(aid, (byte) 0);
}
/**
* Sends a DELETE APDU with the given AID
* @param aid the AID to the delete
* @param p2 the P2 value
* @return the raw card response
*
* @throws IOException communication error.
*/
public APDUResponse delete(byte[] aid, byte p2) throws IOException {
byte[] data = new byte[aid.length + 2];
data[0] = 0x4F;
data[1] = (byte) aid.length;
System.arraycopy(aid, 0, data, 2, aid.length);
APDUCommand cmd = new APDUCommand(0x80, INS_DELETE, 0, 0, data);
APDUCommand cmd = new APDUCommand(0x80, INS_DELETE, 0, p2, data);
return this.secureChannel.send(cmd);
}
}
/**
* Loads the Keycard package.