Skip to content

Commit

Permalink
extended SCP03Wrapper to use extended length APDUs (#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsenger authored and martinpaljak committed May 2, 2019
1 parent 05a90c2 commit 5fd2424
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 14 deletions.
12 changes: 12 additions & 0 deletions src/main/java/pro/javacard/gp/GPUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.slf4j.Logger;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -112,6 +113,17 @@ public static byte[] encodeLength(int len) {
return bo.toByteArray();
}

// Encodes APDU LC value, which has either length of 1 byte or 3 bytes (for extended length APDUs)
// If LC is bigger than fits in one byte (255), LC must be encoded in three bytes
public static byte[] encodeLcLength(int lc) {
if(lc>255) {
byte[] lc_ba = ByteBuffer.allocate(4).putInt(lc).array();
return Arrays.copyOfRange(lc_ba, 1, 4);
}
else
return new byte[]{(byte)lc};
}

// Assumes the bignum length must be even
static byte[] positive(byte[] bytes) {
if (bytes[0] == 0 && bytes.length % 2 == 1) {
Expand Down
29 changes: 15 additions & 14 deletions src/main/java/pro/javacard/gp/SCP03Wrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ protected CommandAPDU wrap(CommandAPDU command) throws GPException {
bo.write(command.getINS());
bo.write(command.getP1());
bo.write(command.getP2());
bo.write(lc);
bo.write(GPUtils.encodeLcLength(lc));
bo.write(data);
byte[] cmac_input = bo.toByteArray();
byte[] cmac = GPCrypto.scp03_mac(sessionKeys.getKeyFor(GPSessionKeyProvider.KeyPurpose.MAC), cmac_input, 128);
Expand All @@ -94,21 +94,22 @@ protected CommandAPDU wrap(CommandAPDU command) throws GPException {
// 8 bytes for actual mac
cmd_mac = Arrays.copyOf(cmac, 8);
}
// Construct new command
ByteArrayOutputStream na = new ByteArrayOutputStream();
na.write(cla); // possibly fiddled
na.write(command.getINS());
na.write(command.getP1());
na.write(command.getP2());
na.write(lc);
na.write(data);
if (mac)
na.write(cmd_mac);
// Constructing new a new command APDU ensures that the coding of LC and NE is correct; especially for Extend Length APDUs
CommandAPDU newAPDU = null;

ByteArrayOutputStream newData = new ByteArrayOutputStream();
newData.write(data);
if (mac) {
newData.write(cmd_mac);
}
if (command.getNe() > 0) {
na.write(command.getNe());
newAPDU = new CommandAPDU(cla, command.getINS(), command.getP1(), command.getP2(),newData.toByteArray(),command.getNe());
}
else {
newAPDU = new CommandAPDU(cla, command.getINS(), command.getP1(), command.getP2(),newData.toByteArray());
}
byte[] new_apdu = na.toByteArray();
return new CommandAPDU(new_apdu);
return newAPDU;

} catch (IOException e) {
throw new RuntimeException("APDU wrapping failed", e);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
Expand Down

0 comments on commit 5fd2424

Please sign in to comment.