Skip to content

Commit

Permalink
Properly parse (also the invalid) SCP version from card recognition data
Browse files Browse the repository at this point in the history
  • Loading branch information
martinpaljak committed Sep 30, 2024
1 parent 7373fca commit 82cf3f8
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 13 deletions.
7 changes: 3 additions & 4 deletions library/src/main/java/pro/javacard/gp/GPData.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,10 @@ public static void pretty_print_card_data(byte[] data) {
for (BerTlv ot : vt.getValues()) {
byte[] oidBytes = ot.getBytesValue();
String oid = logAndGetOidFromByteArray(ot.getTag().bytes, oidBytes);
if (oid.startsWith("1.2.840.114283.4")) {
// This also works with the invalid encoding for SCP80 i=00
if (oid.startsWith("1.2.840.114283.4.")) {
byte[] scp = Arrays.copyOfRange(oidBytes, oidBytes.length - 2, oidBytes.length);
if (scp.length == 2) {
System.out.printf("-> GP SCP%02x i=%02x%n", scp[0], scp[1]);
}
System.out.printf("-> GP %s%n", GPSecureChannelVersion.valueOf(scp[0] & 0xFF, scp[1] & 0xFF));
}
}
} else if (vt.isTag(new BerTag(0x65))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public final class GPSecureChannelVersion {
public final SCP scp;

public enum SCP {
SCP01(1), SCP02(2), SCP03(3);
SCP01(1), SCP02(2), SCP03(3), SCP80(0x80);

private final int value;

Expand Down
7 changes: 5 additions & 2 deletions library/src/main/java/pro/javacard/gp/GPSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,12 @@ private void parse_select_response(byte[] fci) throws GPException {
logger.debug("Auto-detected GP version: " + GPData.oid2version(veroid.getBytesValue()));
}
}
} else if (GPData.oid2string(oidtag.getBytesValue()).startsWith("1.2.840.114283.4.") && oidtag.getBytesValue().length == 9) {
byte[] data = oidtag.getBytesValue();
// SCP version
logger.debug("Auto-detected SCP version: {}", GPSecureChannelVersion.valueOf(data[7] & 0xFF, data[8] & 0xFF));
} else {
// FIXME: this is BS here.
logger.warn("Invalid CardRecognitionData", oidtag.getBytesValue());
logger.warn("Unrecognized card recgnition data: {}", HexUtils.bin2hex(oidtag.getBytesValue()));
}
} else {
logger.warn("Not global platform OID");
Expand Down
26 changes: 21 additions & 5 deletions tool/src/main/java/pro/javacard/gptool/Key.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import apdu4j.core.HexUtils;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
Expand All @@ -32,14 +33,15 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.RSAPublicKeySpec;
import java.util.Optional;

// Helper to convert command line parameters to meaningful key objects.
Expand Down Expand Up @@ -90,10 +92,24 @@ public static Key valueOf(String v) {
throw new IllegalArgumentException("Can not read certificate from PEM: " + ce.getMessage());
}
} else if (ohh instanceof PrivateKeyInfo) {
return new Key(v, null, null, new JcaPEMKeyConverter().getPrivateKey((PrivateKeyInfo) ohh));
PrivateKey pk = new JcaPEMKeyConverter().getPrivateKey((PrivateKeyInfo) ohh);
// TODO: do this for other key types as well
if (pk instanceof RSAPrivateKey) {
BigInteger modulus = ((RSAPrivateKey) pk).getModulus();
BigInteger exponent = ((RSAPrivateKey) pk).getPublicExponent();
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, exponent));
return new Key(v, null, publicKey, pk);
} else if (pk instanceof RSAPrivateCrtKey) {
BigInteger modulus = ((RSAPrivateCrtKey) pk).getModulus();
BigInteger exponent = ((RSAPrivateCrtKey) pk).getPublicExponent();
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, exponent));
return new Key(v, null, publicKey, pk);
} else {
return new Key(v, null, null, pk);
}
} else throw new IllegalArgumentException("Can not read PEM");
}
} catch (IOException e) {
} catch (IOException | GeneralSecurityException e) {
throw new IllegalArgumentException("Could not read PEM: " + e.getMessage(), e);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void testBadFile() {
public void testPrivateOnly() {
Key k = Key.valueOf("../library/src/test/resources/test-dap-rsa-1k-priv.pem");
Assert.assertFalse(k.getSymmetric().isPresent());
Assert.assertFalse(k.getPublic().isPresent());
Assert.assertTrue(k.getPublic().isPresent());
Assert.assertTrue(k.getPrivate().isPresent());
}

Expand Down

0 comments on commit 82cf3f8

Please sign in to comment.