aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cz/crcs/ectester/applet/ECKeyTester.java50
-rw-r--r--src/cz/crcs/ectester/applet/ECTesterApplet.java148
-rw-r--r--src/cz/crcs/ectester/applet/EC_Consts.java45
-rw-r--r--src/cz/crcs/ectester/common/util/CardUtil.java52
-rw-r--r--src/cz/crcs/ectester/reader/ECTesterReader.java4
-rw-r--r--src/cz/crcs/ectester/reader/command/Command.java113
-rw-r--r--src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java2
-rw-r--r--src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java2
-rw-r--r--src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java2
-rw-r--r--src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java2
-rw-r--r--src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java4
11 files changed, 347 insertions, 77 deletions
diff --git a/src/cz/crcs/ectester/applet/ECKeyTester.java b/src/cz/crcs/ectester/applet/ECKeyTester.java
index 27bb9e1..7c091e3 100644
--- a/src/cz/crcs/ectester/applet/ECKeyTester.java
+++ b/src/cz/crcs/ectester/applet/ECKeyTester.java
@@ -130,6 +130,56 @@ public class ECKeyTester {
return length;
}
+ /**
+ *
+ * @param signKey
+ * @param inputBuffer
+ * @param inputOffset
+ * @param inputLength
+ * @param sigBuffer
+ * @param sigOffset
+ * @return
+ */
+ public short testECDSA_sign(ECPrivateKey signKey, byte[] inputBuffer, short inputOffset, short inputLength, byte[] sigBuffer, short sigOffset) {
+ short length = 0;
+ try {
+ sw = AppletUtil.signCheck(ecdsaSignature);
+
+ ecdsaSignature.init(signKey, Signature.MODE_SIGN);
+ length = ecdsaSignature.sign(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset);
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ *
+ * @param verifyKey
+ * @param inputBuffer
+ * @param inputOffset
+ * @param inputLength
+ * @param sigBuffer
+ * @param sigOffset
+ * @param sigLength
+ * @return
+ */
+ public short testECDSA_verify(ECPublicKey verifyKey, byte[] inputBuffer, short inputOffset, short inputLength, byte[] sigBuffer, short sigOffset, short sigLength) {
+ short length = 0;
+ try {
+ sw = AppletUtil.signCheck(ecdsaSignature);
+
+ ecdsaSignature.init(verifyKey, Signature.MODE_VERIFY);
+ boolean correct = ecdsaSignature.verify(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset, sigLength);
+ if (!correct) {
+ sw = ECTesterApplet.SW_SIG_VERIFY_FAIL;
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
public KeyAgreement getKA() {
return ecKeyAgreement;
}
diff --git a/src/cz/crcs/ectester/applet/ECTesterApplet.java b/src/cz/crcs/ectester/applet/ECTesterApplet.java
index 18c4d1f..d0ca8f5 100644
--- a/src/cz/crcs/ectester/applet/ECTesterApplet.java
+++ b/src/cz/crcs/ectester/applet/ECTesterApplet.java
@@ -51,10 +51,11 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
public static final byte INS_ECDH = (byte) 0x70;
public static final byte INS_ECDH_DIRECT = (byte) 0x71;
public static final byte INS_ECDSA = (byte) 0x72;
- public static final byte INS_CLEANUP = (byte) 0x73;
- //public static final byte INS_SUPPORT = (byte) 0x74;
- public static final byte INS_ALLOCATE_KA = (byte) 0x75;
- public static final byte INS_ALLOCATE_SIG = (byte) 0x76;
+ public static final byte INS_ECDSA_SIGN = (byte) 0x73;
+ public static final byte INS_ECDSA_VERIFY = (byte) 0x74;
+ public static final byte INS_CLEANUP = (byte) 0x75;
+ public static final byte INS_ALLOCATE_KA = (byte) 0x76;
+ public static final byte INS_ALLOCATE_SIG = (byte) 0x77;
// PARAMETERS for P1 and P2
@@ -83,34 +84,12 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
public static final short SW_TransactionException_prefix = (short) 0xf400;
public static final short SW_CardRuntimeException_prefix = (short) 0xf500;
-
- // Class javacard.security.KeyAgreement
- // javacard.security.KeyAgreement Fields:
- public static final byte KeyAgreement_ALG_EC_SVDP_DH = 1;
- public static final byte KeyAgreement_ALG_EC_SVDP_DH_KDF = 1;
- public static final byte KeyAgreement_ALG_EC_SVDP_DHC = 2;
- public static final byte KeyAgreement_ALG_EC_SVDP_DHC_KDF = 2;
- public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN = 3;
- public static final byte KeyAgreement_ALG_EC_SVDP_DHC_PLAIN = 4;
- public static final byte KeyAgreement_ALG_EC_PACE_GM = 5;
- public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY = 6;
-
- // Class javacard.security.Signature
- // javacard.security.Signature Fields:
- public static final byte Signature_ALG_ECDSA_SHA = 17;
- public static final byte Signature_ALG_ECDSA_SHA_256 = 33;
- public static final byte Signature_ALG_ECDSA_SHA_384 = 34;
- public static final byte Signature_ALG_ECDSA_SHA_224 = 37;
- public static final byte Signature_ALG_ECDSA_SHA_512 = 38;
-
private static final short ARRAY_LENGTH = (short) 0xff;
private static final short APDU_MAX_LENGTH = (short) 1024;
// TEMPORARRY ARRAY IN RAM
private byte[] ramArray = null;
private byte[] ramArray2 = null;
private byte[] apduArray = null;
- // PERSISTENT ARRAY IN EEPROM
- private byte[] dataArray = null; // unused
private RandomData randomData = null;
@@ -135,9 +114,6 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
ramArray2 = JCSystem.makeTransientByteArray(ARRAY_LENGTH, JCSystem.CLEAR_ON_RESET);
apduArray = JCSystem.makeTransientByteArray(APDU_MAX_LENGTH, JCSystem.CLEAR_ON_RESET);
- dataArray = new byte[ARRAY_LENGTH];
- Util.arrayFillNonAtomic(dataArray, (short) 0, ARRAY_LENGTH, (byte) 0);
-
randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
EC_Consts.randomData = randomData;
@@ -203,6 +179,12 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
case INS_ECDSA:
length = insECDSA(apdu);
break;
+ case INS_ECDSA_SIGN:
+ length = insECDSA_sign(apdu);
+ break;
+ case INS_ECDSA_VERIFY:
+ length = insECDSA_verify(apdu);
+ break;
case INS_CLEANUP:
length = insCleanup(apdu);
break;
@@ -495,6 +477,57 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
}
/**
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_*)
+ * P2 = byte export (EXPORT_TRUE || EXPORT_FALSE)
+ * DATA = byte sigType
+ * short dataLength (00 = random data generated, !00 = data length)
+ * byte[] data
+ * @return length of response
+ */
+ private short insECDSA_sign(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte export = apduArray[ISO7816.OFFSET_P2];
+ short cdata = apdu.getOffsetCdata();
+ byte sigType = apduArray[cdata];
+
+ short len = 0;
+ if ((keyPair & KEYPAIR_LOCAL) != 0) {
+ len += ecdsa_sign(localKeypair, sigType, export, apduArray, (short) (cdata + 1), apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & KEYPAIR_REMOTE) != 0) {
+ len += ecdsa_sign(remoteKeypair, sigType, export, apduArray, (short) (cdata + 1), apdu.getBuffer(), len);
+ }
+ return len;
+ }
+
+ /**
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_*)
+ * P2 = byte sigType
+ * DATA = short dataLength (00 = random data generated, !00 = data length)
+ * byte[] data
+ * short sigLength
+ * byte[] signature
+ * @return length of response
+ */
+ private short insECDSA_verify(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte sigType = apduArray[ISO7816.OFFSET_P2];
+ short cdata = apdu.getOffsetCdata();
+
+ short len = 0;
+ if ((keyPair & KEYPAIR_LOCAL) != 0) {
+ len += ecdsa_verify(localKeypair, sigType, apduArray, cdata, apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & KEYPAIR_REMOTE) != 0) {
+ len += ecdsa_verify(remoteKeypair, sigType, apduArray, cdata, apdu.getBuffer(), len);
+ }
+ return len;
+ }
+
+
+ /**
* Performs card memory cleanup via JCSystem.requestObjectDeletion()
*
* @param apdu no data
@@ -741,6 +774,63 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
return length;
}
+ private short ecdsa_sign(KeyPair sign, byte sigType, byte export, byte[] inBuffer, short inOffset, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ short dataLength = Util.getShort(inBuffer, inOffset);
+ if (dataLength == 0) { //no data to sign
+ //generate random
+ dataLength = 64;
+ randomData.generateData(ramArray, (short) 0, dataLength);
+ } else {
+ Util.arrayCopyNonAtomic(inBuffer, (short) (inOffset + 2), ramArray, (short) 0, dataLength);
+ }
+
+ short signatureLength = 0;
+ if (keyTester.getSigType() == sigType) {
+ signatureLength = keyTester.testECDSA_sign((ECPrivateKey) sign.getPrivate(), ramArray, (short) 0, dataLength, ramArray2, (short) 0);
+ } else {
+ short allocateSW = keyTester.allocateSig(sigType);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ signatureLength = keyTester.testECDSA_sign((ECPrivateKey) sign.getPrivate(), ramArray, (short) 0, dataLength, ramArray2, (short) 0);
+ }
+ }
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ if (export == EXPORT_TRUE) {
+ Util.setShort(outBuffer, (short) (outOffset + length), signatureLength);
+ length += 2;
+
+ Util.arrayCopyNonAtomic(ramArray2, (short) 0, outBuffer, (short) (outOffset + length), signatureLength);
+ length += signatureLength;
+ }
+
+ return length;
+ }
+
+ private short ecdsa_verify(KeyPair verify, byte sigType, byte[] inBuffer, short inOffset, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ short dataLength = Util.getShort(inBuffer, inOffset);
+ short dataOffset = (short)(inOffset + 2);
+ short sigLength = Util.getShort(inBuffer, (short)(dataOffset + dataLength));
+ short sigOffset = (short)(dataOffset + dataLength + 2);
+
+ if (keyTester.getSigType() == sigType) {
+ keyTester.testECDSA_verify((ECPublicKey) verify.getPublic(), inBuffer, dataOffset, dataLength, inBuffer, sigOffset, sigLength);
+ } else {
+ short allocateSW = keyTester.allocateSig(sigType);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ keyTester.testECDSA_verify((ECPublicKey) verify.getPublic(), inBuffer, dataOffset, dataLength, inBuffer, sigOffset, sigLength);
+ }
+ }
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ return length;
+ }
+
/**
* @param buffer buffer to write sw to
* @param offset output offset in buffer
diff --git a/src/cz/crcs/ectester/applet/EC_Consts.java b/src/cz/crcs/ectester/applet/EC_Consts.java
index 5b3c74c..88a8bd6 100644
--- a/src/cz/crcs/ectester/applet/EC_Consts.java
+++ b/src/cz/crcs/ectester/applet/EC_Consts.java
@@ -12,6 +12,8 @@ import javacard.security.RandomData;
*/
public class EC_Consts {
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_KDF = 1;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC_KDF = 2;
private static byte[] EC_FP_P = null; //p
private static byte[] EC_A = null; //a
private static byte[] EC_B = null; //b
@@ -1026,23 +1028,40 @@ public class EC_Consts {
public static final short[] FP_SIZES = new short[]{112, 128, 160, 192, 224, 256, 384, 521};
public static final short[] F2M_SIZES = new short[]{163, 233, 283, 409, 571};
+ // Class javacard.security.KeyAgreement
+ // javacard.security.KeyAgreement Fields:
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH = 1;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC = 2;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN = 3;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC_PLAIN = 4;
+ public static final byte KeyAgreement_ALG_EC_PACE_GM = 5;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY = 6;
+
public static final byte[] KA_TYPES = new byte[]{
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH,
- //ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH_KDF, //duplicate
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DHC,
- //ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DHC_KDF, //duplicate
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH_PLAIN,
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DHC_PLAIN,
- ECTesterApplet.KeyAgreement_ALG_EC_PACE_GM,
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY
+ KeyAgreement_ALG_EC_SVDP_DH,
+ //KeyAgreement_ALG_EC_SVDP_DH_KDF, //duplicate
+ KeyAgreement_ALG_EC_SVDP_DHC,
+ //KeyAgreement_ALG_EC_SVDP_DHC_KDF, //duplicate
+ KeyAgreement_ALG_EC_SVDP_DH_PLAIN,
+ KeyAgreement_ALG_EC_SVDP_DHC_PLAIN,
+ KeyAgreement_ALG_EC_PACE_GM,
+ KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY
};
+ // Class javacard.security.Signature
+ // javacard.security.Signature Fields:
+ public static final byte Signature_ALG_ECDSA_SHA = 17;
+ public static final byte Signature_ALG_ECDSA_SHA_224 = 37;
+ public static final byte Signature_ALG_ECDSA_SHA_256 = 33;
+ public static final byte Signature_ALG_ECDSA_SHA_384 = 34;
+ public static final byte Signature_ALG_ECDSA_SHA_512 = 38;
+
public static final byte[] SIG_TYPES = new byte[]{
- ECTesterApplet.Signature_ALG_ECDSA_SHA,
- ECTesterApplet.Signature_ALG_ECDSA_SHA_224,
- ECTesterApplet.Signature_ALG_ECDSA_SHA_256,
- ECTesterApplet.Signature_ALG_ECDSA_SHA_384,
- ECTesterApplet.Signature_ALG_ECDSA_SHA_512
+ Signature_ALG_ECDSA_SHA,
+ Signature_ALG_ECDSA_SHA_224,
+ Signature_ALG_ECDSA_SHA_256,
+ Signature_ALG_ECDSA_SHA_384,
+ Signature_ALG_ECDSA_SHA_512
};
public static byte getCurve(short keyLength, byte keyClass) {
diff --git a/src/cz/crcs/ectester/common/util/CardUtil.java b/src/cz/crcs/ectester/common/util/CardUtil.java
index 3df5829..2501e47 100644
--- a/src/cz/crcs/ectester/common/util/CardUtil.java
+++ b/src/cz/crcs/ectester/common/util/CardUtil.java
@@ -6,8 +6,6 @@ import javacard.framework.ISO7816;
import javacard.security.CryptoException;
import javacard.security.KeyPair;
-import static cz.crcs.ectester.applet.ECTesterApplet.*;
-
/**
* @author Petr Svenda petr@svenda.com
* @author Jan Jancar johny@neuromancer.sk
@@ -17,12 +15,12 @@ public class CardUtil {
switch (name) {
case "DH":
case "ECDH":
- return ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
case "DHC":
case "ECDHC":
- return ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DHC;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC;
default:
- return ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
}
}
@@ -208,17 +206,17 @@ public class CardUtil {
public static String getKATypeString(byte kaType) {
switch (kaType) {
- case KeyAgreement_ALG_EC_SVDP_DH:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DH:
return "ALG_EC_SVDP_DH";
- case KeyAgreement_ALG_EC_SVDP_DH_PLAIN:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN:
return "ALG_EC_SVDP_DH_PLAIN";
- case KeyAgreement_ALG_EC_PACE_GM:
+ case EC_Consts.KeyAgreement_ALG_EC_PACE_GM:
return "ALG_EC_PACE_GM";
- case KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY:
return "ALG_EC_SVDP_DH_PLAIN_XY";
- case KeyAgreement_ALG_EC_SVDP_DHC:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC:
return "ALG_EC_SVDP_DHC";
- case KeyAgreement_ALG_EC_SVDP_DHC_PLAIN:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC_PLAIN:
return "ALG_EC_SVDP_DHC_PLAIN";
default:
return "unknown";
@@ -228,17 +226,17 @@ public class CardUtil {
public static byte getKAType(String kaTypeString) {
switch (kaTypeString) {
case "ALG_EC_SVDP_DH":
- return KeyAgreement_ALG_EC_SVDP_DH;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
case "ALG_EC_SVDP_DH_PLAIN":
- return KeyAgreement_ALG_EC_SVDP_DH_PLAIN;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN;
case "ALG_EC_PACE_GM":
- return KeyAgreement_ALG_EC_PACE_GM;
+ return EC_Consts.KeyAgreement_ALG_EC_PACE_GM;
case "ALG_EC_SVDP_DH_PLAIN_XY":
- return KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY;
case "ALG_EC_SVDP_DHC":
- return KeyAgreement_ALG_EC_SVDP_DHC;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC;
case "ALG_EC_SVDP_DHC_PLAIN":
- return KeyAgreement_ALG_EC_SVDP_DHC_PLAIN;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC_PLAIN;
default:
return 0;
}
@@ -256,15 +254,15 @@ public class CardUtil {
public static String getSigTypeString(byte sigType) {
switch (sigType) {
- case Signature_ALG_ECDSA_SHA:
+ case EC_Consts.Signature_ALG_ECDSA_SHA:
return "ALG_ECDSA_SHA";
- case Signature_ALG_ECDSA_SHA_224:
+ case EC_Consts.Signature_ALG_ECDSA_SHA_224:
return "ALG_ECDSA_SHA_224";
- case Signature_ALG_ECDSA_SHA_256:
+ case EC_Consts.Signature_ALG_ECDSA_SHA_256:
return "ALG_ECDSA_SHA_256";
- case Signature_ALG_ECDSA_SHA_384:
+ case EC_Consts.Signature_ALG_ECDSA_SHA_384:
return "ALG_ECDSA_SHA_384";
- case Signature_ALG_ECDSA_SHA_512:
+ case EC_Consts.Signature_ALG_ECDSA_SHA_512:
return "ALG_ECDSA_SHA_512";
default:
return "unknown";
@@ -274,15 +272,15 @@ public class CardUtil {
public static byte getSigType(String sigTypeString) {
switch (sigTypeString) {
case "ALG_ECDSA_SHA":
- return Signature_ALG_ECDSA_SHA;
+ return EC_Consts.Signature_ALG_ECDSA_SHA;
case "ALG_ECDSA_SHA_224":
- return Signature_ALG_ECDSA_SHA_224;
+ return EC_Consts.Signature_ALG_ECDSA_SHA_224;
case "ALG_ECDSA_SHA_256":
- return Signature_ALG_ECDSA_SHA_256;
+ return EC_Consts.Signature_ALG_ECDSA_SHA_256;
case "ALG_ECDSA_SHA_384":
- return Signature_ALG_ECDSA_SHA_384;
+ return EC_Consts.Signature_ALG_ECDSA_SHA_384;
case "ALG_ECDSA_SHA_512":
- return Signature_ALG_ECDSA_SHA_512;
+ return EC_Consts.Signature_ALG_ECDSA_SHA_512;
default:
return 0;
}
diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java
index dfd71db..84c0439 100644
--- a/src/cz/crcs/ectester/reader/ECTesterReader.java
+++ b/src/cz/crcs/ectester/reader/ECTesterReader.java
@@ -49,8 +49,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
-import static cz.crcs.ectester.applet.ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH;
-import static cz.crcs.ectester.applet.ECTesterApplet.Signature_ALG_ECDSA_SHA;
+import static cz.crcs.ectester.applet.EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
+import static cz.crcs.ectester.applet.EC_Consts.Signature_ALG_ECDSA_SHA;
/**
* Reader part of ECTester, a tool for testing Elliptic curve support on javacards.
diff --git a/src/cz/crcs/ectester/reader/command/Command.java b/src/cz/crcs/ectester/reader/command/Command.java
index 25b41dd..d0eaf45 100644
--- a/src/cz/crcs/ectester/reader/command/Command.java
+++ b/src/cz/crcs/ectester/reader/command/Command.java
@@ -685,6 +685,10 @@ public abstract class Command {
*/
public ECDSA(CardMngr cardManager, byte keyPair, byte sigType, byte export, byte[] raw) {
super(cardManager);
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ throw new IllegalArgumentException();
+ }
+
this.keyPair = keyPair;
this.sigType = sigType;
this.export = export;
@@ -718,6 +722,115 @@ public abstract class Command {
}
}
+ public static class ECDSA_sign extends Command {
+ private byte keyPair;
+ private byte sigType;
+ private byte export;
+ private byte[] raw;
+
+ /**
+ * Creates the INS_ECDSA_SIGN instruction.
+ *
+ * @param cardManager cardManager to send APDU through
+ * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
+ * @param sigType Signature type to use
+ * @param export whether to export ECDSA signature
+ * @param raw data to sign, can be null, in which case random data is signed.
+ */
+ public ECDSA_sign(CardMngr cardManager, byte keyPair, byte sigType, byte export, byte[] raw) {
+ super(cardManager);
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ throw new IllegalArgumentException();
+ }
+
+ this.keyPair = keyPair;
+ this.sigType = sigType;
+ this.export = export;
+ this.raw = raw;
+
+ int len = raw != null ? raw.length : 0;
+ byte[] data = new byte[3 + len];
+ data[0] = sigType;
+ ByteUtil.setShort(data, 1, (short) len);
+ if (raw != null) {
+ System.arraycopy(raw, 0, data, 3, len);
+ }
+
+ this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA_SIGN, keyPair, export, data);
+ }
+
+ @Override
+ public Response.ECDSA send() throws CardException {
+ long elapsed = -System.nanoTime();
+ ResponseAPDU response = cardManager.send(cmd);
+ elapsed += System.nanoTime();
+ return new Response.ECDSA(response, getDescription(), elapsed, keyPair, sigType, export, raw);
+ }
+
+ @Override
+ public String getDescription() {
+ String algo = CardUtil.getSigTypeString(sigType);
+ String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
+ String data = raw == null ? "random" : "provided";
+ return String.format("%s signature with %s keypair(%s data)", algo, key, data);
+ }
+ }
+
+ public static class ECDSA_verify extends Command {
+ private byte keyPair;
+ private byte sigType;
+ private byte[] raw;
+ private byte[] signature;
+
+ /**
+ * Creates the INS_ECDSA_VERIFY instruction.
+ *
+ * @param cardManager cardManager to send APDU through
+ * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
+ * @param sigType Signature type to use
+ * @param raw data to sign
+ * @param signature signature data
+ */
+ public ECDSA_verify(CardMngr cardManager, byte keyPair, byte sigType, byte[] raw, byte[] signature) {
+ super(cardManager);
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ throw new IllegalArgumentException();
+ }
+ if (raw == null || signature == null) {
+ throw new IllegalArgumentException();
+ }
+
+ this.keyPair = keyPair;
+ this.sigType = sigType;
+ this.raw = raw;
+ this.signature = signature;
+
+ byte[] data = new byte[4 + raw.length + signature.length];
+ ByteUtil.setShort(data, 0, (short) raw.length);
+ System.arraycopy(raw, 0, data, 2, raw.length);
+ ByteUtil.setShort(data, 2 + raw.length, (short) signature.length);
+ System.arraycopy(signature, 0, data, 2 + raw.length + 2, signature.length);
+
+ this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA_SIGN, keyPair, sigType, data);
+ }
+
+ @Override
+ public Response.ECDSA send() throws CardException {
+ long elapsed = -System.nanoTime();
+ ResponseAPDU response = cardManager.send(cmd);
+ elapsed += System.nanoTime();
+ return new Response.ECDSA(response, getDescription(), elapsed, keyPair, sigType, ECTesterApplet.EXPORT_FALSE, raw);
+ }
+
+ @Override
+ public String getDescription() {
+ String algo = CardUtil.getSigTypeString(sigType);
+ String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
+ String data = raw == null ? "random" : "provided";
+ return String.format("%s verification with %s keypair(%s data)", algo, key, data);
+ }
+ }
+
/**
*
*/
diff --git a/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java b/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java
index a0b71a7..1ca05d4 100644
--- a/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java
@@ -48,7 +48,7 @@ public class CardCofactorTestSuite extends CardTestSuite {
List<Test> ecdhTests = new LinkedList<>();
for (EC_Key.Public pub : keys) {
- Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
ecdhTests.add(CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on non-generator subgroup.", "Card incorrectly accepted point on non-generator subgroup."));
}
Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with public points on non-generator subgroup", ecdhTests.toArray(new Test[0]));
diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java
index f0eaa87..95204dd 100644
--- a/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java
@@ -39,7 +39,7 @@ public class CardCompositeCurvesSuite extends CardTestSuite {
Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS);
Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY);
Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.ANY);
- Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH, key.flatten());
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, key.flatten());
Test ecdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a composite order curve.", "Card incorrectly does ECDH over a composite order curve, leaks bits of private key.");
doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", " + key.getDesc(), allocate, set, generate, ecdh));
diff --git a/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java
index fab7786..d3c5f99 100644
--- a/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java
@@ -53,7 +53,7 @@ public class CardInvalidCurvesSuite extends CardTestSuite {
List<Test> ecdhTests = new LinkedList<>();
for (EC_Key.Public pub : keys) {
- Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
ecdhTests.add(CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on invalid curve.", "Card incorrectly accepted point on invalid curve."));
}
Test ecdh = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH with invalid public points", ecdhTests.toArray(new Test[0]));
diff --git a/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java b/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java
index 4b90694..c80db0d 100644
--- a/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java
@@ -48,7 +48,7 @@ public class CardTwistTestSuite extends CardTestSuite {
List<Test> ecdhTests = new LinkedList<>();
for (EC_Key.Public pub : keys) {
- Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
ecdhTests.add(CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on twist.", "Card incorrectly accepted point on twist."));
}
Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with public points on twist", ecdhTests.toArray(new Test[0]));
diff --git a/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java
index 5d58be1..429b047 100644
--- a/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java
@@ -146,8 +146,8 @@ public class CardWrongCurvesSuite extends CardTestSuite {
Test setup = runTest(CommandTest.expect(setupCmd, Result.ExpectedValue.FAILURE));
Test generate = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.FAILURE));
Test preparePhase = runTest(CompoundTest.any(Result.ExpectedValue.SUCCESS, prepareDesc, setup, generate));
- Test allocateECDH = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.SUCCESS));
- Test ecdh = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE));
+ Test allocateECDH = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.SUCCESS));
+ Test ecdh = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE));
return runTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, fullDesc, preparePhase, allocateECDH, ecdh));
}
}