aboutsummaryrefslogtreecommitdiff
path: root/applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java
diff options
context:
space:
mode:
Diffstat (limited to 'applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java')
-rw-r--r--applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java225
1 files changed, 225 insertions, 0 deletions
diff --git a/applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java b/applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java
new file mode 100644
index 0000000..3af1cca
--- /dev/null
+++ b/applet/src/main/java/cz/crcs/ectester/applet/ECKeyTester.java
@@ -0,0 +1,225 @@
+package cz.crcs.ectester.applet;
+
+
+import javacard.framework.CardRuntimeException;
+import javacard.framework.ISO7816;
+import javacard.security.*;
+
+/**
+ * Class capable of testing ECDH/C and ECDSA.
+ * Note that ECDH and ECDHC output should equal, only the algorithm is different.
+ *
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class ECKeyTester {
+ private KeyAgreement ecKeyAgreement = null;
+ private short kaType = 0;
+ private Signature ecdsaSignature = null;
+ private short sigType = 0;
+
+ private short sw = ISO7816.SW_NO_ERROR;
+ private boolean dryRun = false;
+
+ public short allocateKA(byte algorithm) {
+ sw = ISO7816.SW_NO_ERROR;
+ try {
+ if (!dryRun) {
+ ecKeyAgreement = KeyAgreement.getInstance(algorithm, false);
+ kaType = algorithm;
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return sw;
+ }
+
+ public short allocateSig(byte algorithm) {
+ sw = ISO7816.SW_NO_ERROR;
+ try {
+ if (!dryRun) {
+ ecdsaSignature = Signature.getInstance(algorithm, false);
+ sigType = algorithm;
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return sw;
+ }
+
+ /**
+ * Tests ECDH secret generation with keys from given {@code privatePair} and {@code publicPair}.
+ * Uses {@code pubkeyBuffer} at {@code pubkeyOffset} for computations.
+ * Output should equal with ECDHC output.
+ *
+ * @param privatePair KeyPair from which the private key is used
+ * @param publicPair KeyPair from which the public key is used
+ * @param pubkeyBuffer buffer to be used for the public key
+ * @param pubkeyOffset offset into pubkeyBuffer that can be used for the public key
+ * @param outputBuffer buffer to be used for the secret output
+ * @param outputOffset offset into the outputBuffer
+ * @param transformation (EC_Consts.TRANSFORMATION_* | ...)
+ * @return derived secret length
+ **/
+ public short testKA(KeyPair privatePair, KeyPair publicPair, byte[] pubkeyBuffer, short pubkeyOffset, byte[] outputBuffer, short outputOffset, short transformation) {
+ short length = 0;
+ try {
+ sw = AppletUtil.kaCheck(ecKeyAgreement);
+ sw = AppletUtil.keypairCheck(privatePair);
+ sw = AppletUtil.keypairCheck(publicPair);
+ if (!dryRun) {
+ short pubkeyLength = ((ECPublicKey) publicPair.getPublic()).getW(pubkeyBuffer, pubkeyOffset);
+ ecKeyAgreement.init(privatePair.getPrivate());
+
+ pubkeyLength = EC_Consts.transformParameter(transformation, pubkeyBuffer, pubkeyOffset, pubkeyLength);
+ length = ecKeyAgreement.generateSecret(pubkeyBuffer, pubkeyOffset, pubkeyLength, outputBuffer, outputOffset);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ * @param privatePair
+ * @param pubkey
+ * @param pubkeyOffset
+ * @param pubkeyLength
+ * @param outpuBuffer
+ * @param outputOffset
+ * @param transformation
+ * @return
+ */
+ public short testKA_direct(KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outpuBuffer, short outputOffset, short transformation) {
+ short length = 0;
+ try {
+ sw = AppletUtil.kaCheck(ecKeyAgreement);
+ sw = AppletUtil.keypairCheck(privatePair);
+
+ if (!dryRun) {
+ ecKeyAgreement.init(privatePair.getPrivate());
+ pubkeyLength = EC_Consts.transformParameter(transformation, pubkey, pubkeyOffset, pubkeyLength);
+ length = ecKeyAgreement.generateSecret(pubkey, pubkeyOffset, pubkeyLength, outpuBuffer, outputOffset);
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ * Uses {@code signKey} to sign data from {@code inputBuffer} at {@code inputOffset} with {@code inputOffset}.
+ * Then checks for correct signature length.
+ * Then tries verifying the data with {@code verifyKey}.
+ *
+ * @param signKey key to use for signing
+ * @param verifyKey key to use for verifying the signature
+ * @param inputBuffer buffer to sign data from
+ * @param inputOffset offset into inputBuffer to sign data from
+ * @param inputLength length of data to sign
+ * @param sigBuffer buffer to output signature to
+ * @param sigOffset offset into sigBuffer to output to
+ * @return signature length
+ */
+ public short testECDSA(ECPrivateKey signKey, ECPublicKey verifyKey, byte[] inputBuffer, short inputOffset, short inputLength, byte[] sigBuffer, short sigOffset) {
+ short length = 0;
+ try {
+ sw = AppletUtil.signCheck(ecdsaSignature);
+
+ if (!dryRun) {
+ ecdsaSignature.init(signKey, Signature.MODE_SIGN);
+ length = ecdsaSignature.sign(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset);
+
+ ecdsaSignature.init(verifyKey, Signature.MODE_VERIFY);
+ if (!ecdsaSignature.verify(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset, length)) {
+ sw = CardConsts.SW_SIG_VERIFY_FAIL;
+ }
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ 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);
+
+ if (!dryRun) {
+ 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);
+
+ if (!dryRun) {
+ ecdsaSignature.init(verifyKey, Signature.MODE_VERIFY);
+ if (!ecdsaSignature.verify(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset, sigLength)) {
+ sw = CardConsts.SW_SIG_VERIFY_FAIL;
+ }
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ public KeyAgreement getKA() {
+ return ecKeyAgreement;
+ }
+
+ public Signature getSig() {
+ return ecdsaSignature;
+ }
+
+ public boolean hasKA() {
+ return ecKeyAgreement != null;
+ }
+
+ public boolean hasSig() {
+ return ecdsaSignature != null;
+ }
+
+ public short getKaType() {
+ return kaType;
+ }
+
+ public short getSigType() {
+ return sigType;
+ }
+
+ public short getSW() {
+ return sw;
+ }
+
+ public void setDryRun(boolean dryRun) {
+ this.dryRun = dryRun;
+ }
+}