diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cz/crcs/ectester/applet/AppletUtil.java | 1 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECKeyTester.java | 45 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECTesterApplet.java | 65 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/EC_Consts.java | 85 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/Command.java | 35 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/TestSuite.java | 12 |
6 files changed, 220 insertions, 23 deletions
diff --git a/src/cz/crcs/ectester/applet/AppletUtil.java b/src/cz/crcs/ectester/applet/AppletUtil.java index 296541d..532b44e 100644 --- a/src/cz/crcs/ectester/applet/AppletUtil.java +++ b/src/cz/crcs/ectester/applet/AppletUtil.java @@ -51,7 +51,6 @@ public class AppletUtil { sum += read; read = apdu.receiveBytes((short) 0); } while (sum < total); - // TODO figure this out, in buffer + out buffer(apdubuf) or just send each param on its own? return 0; } } diff --git a/src/cz/crcs/ectester/applet/ECKeyTester.java b/src/cz/crcs/ectester/applet/ECKeyTester.java index 7664c72..b18073f 100644 --- a/src/cz/crcs/ectester/applet/ECKeyTester.java +++ b/src/cz/crcs/ectester/applet/ECKeyTester.java @@ -66,6 +66,21 @@ public class ECKeyTester { return length; } + private short testKA_direct(KeyAgreement ka, KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outpuBuffer, short outputOffset, short corruption) { + short length = 0; + try { + sw = AppletUtil.kaCheck(ka); + sw = AppletUtil.keypairCheck(privatePair); + + ka.init(privatePair.getPrivate()); + pubkeyLength = EC_Consts.corruptParameter(corruption, pubkey, pubkeyOffset, pubkeyLength); + length = ka.generateSecret(pubkey, pubkeyOffset, pubkeyLength, outpuBuffer, outputOffset); + } catch (CardRuntimeException ce) { + sw = ce.getReason(); + } + return length; + } + /** * Tests ECDH secret generation with keys from given {@code privatePair} and {@code publicPair}. * Uses {@code pubkeyBuffer} at {@code pubkeyOffset} for computations. @@ -84,6 +99,10 @@ public class ECKeyTester { return testKA(ecdhKeyAgreement, privatePair, publicPair, pubkeyBuffer, pubkeyOffset, outputBuffer, outputOffset, corruption); } + public short testECDH_direct(KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outpuBuffer, short outputOffset, short corruption) { + return testKA_direct(ecdhKeyAgreement, privatePair, pubkey, pubkeyOffset, pubkeyLength, outpuBuffer, outputOffset, corruption); + } + /** * Tests ECDHC secret generation with keys from given {@code privatePair} and {@code publicPair}. * Uses {@code pubkeyBuffer} at {@code pubkeyOffset} for computations. @@ -102,6 +121,10 @@ public class ECKeyTester { return testKA(ecdhcKeyAgreement, privatePair, publicPair, pubkeyBuffer, pubkeyOffset, outputBuffer, outputOffset, corruption); } + public short testECDHC_direct(KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outpuBuffer, short outputOffset, short corruption) { + return testKA_direct(ecdhcKeyAgreement, privatePair, pubkey, pubkeyOffset, pubkeyLength, outpuBuffer, outputOffset, corruption); + } + /** * @param privatePair KeyPair from which the private key is used * @param publicPair KeyPair from which the public key is used @@ -126,7 +149,22 @@ public class ECKeyTester { sw = ECTesterApplet.SW_DH_DHC_MISMATCH; } return length; + } + public short testBOTH_direct(KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outputBuffer, short outputOffset, short corruption) { + short ecdhLength = testECDH_direct(privatePair, pubkey, pubkeyOffset, pubkeyLength, outputBuffer, outputOffset, corruption); + if (sw != ISO7816.SW_NO_ERROR) { + return ecdhLength; + } + short ecdhcLength = testECDHC_direct(privatePair, pubkey, pubkeyOffset, pubkeyLength, outputBuffer, outputOffset, corruption); + short length = (short) (ecdhLength + ecdhcLength); + if (sw != ISO7816.SW_NO_ERROR) { + return length; + } + if (javacard.framework.Util.arrayCompare(outputBuffer, outputOffset, outputBuffer, (short) (outputOffset + ecdhLength), ecdhLength) != 0) { + sw = ECTesterApplet.SW_DH_DHC_MISMATCH; + } + return length; } /** @@ -146,6 +184,13 @@ public class ECKeyTester { return testECDHC(privatePair, publicPair, pubkeyBuffer, pubkeyOffset, outputBuffer, outputOffset, corruption); } + public short testANY_direct(KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outputBuffer, short outputOffset, short corruption) { + short ecdhLength = testECDH_direct(privatePair, pubkey, pubkeyOffset, pubkeyLength, outputBuffer, outputOffset, corruption); + if (sw == ISO7816.SW_NO_ERROR) + return ecdhLength; + return testECDHC_direct(privatePair, pubkey, pubkeyOffset, pubkeyLength, outputBuffer, outputOffset, corruption); + } + /** * Uses {@code signKey} to sign data from {@code inputBuffer} at {@code inputOffset} with {@code inputOffset}. * Then checks for correct signature length. diff --git a/src/cz/crcs/ectester/applet/ECTesterApplet.java b/src/cz/crcs/ectester/applet/ECTesterApplet.java index a7d8537..c2e2c63 100644 --- a/src/cz/crcs/ectester/applet/ECTesterApplet.java +++ b/src/cz/crcs/ectester/applet/ECTesterApplet.java @@ -51,9 +51,10 @@ public class ECTesterApplet extends Applet implements ExtendedLength { public static final byte INS_GENERATE = (byte) 0x5e; public static final byte INS_EXPORT = (byte) 0x5f; public static final byte INS_ECDH = (byte) 0x60; - public static final byte INS_ECDSA = (byte) 0x61; - public static final byte INS_CLEANUP = (byte) 0x62; - public static final byte INS_SUPPORT = (byte) 0x63; + public static final byte INS_ECDH_DIRECT = (byte) 0x61; + public static final byte INS_ECDSA = (byte) 0x62; + public static final byte INS_CLEANUP = (byte) 0x63; + public static final byte INS_SUPPORT = (byte) 0x64; // PARAMETERS for P1 and P2 public static final byte KEYPAIR_LOCAL = (byte) 0x01; @@ -164,6 +165,9 @@ public class ECTesterApplet extends Applet implements ExtendedLength { case INS_ECDH: length = insECDH(apdu); break; + case INS_ECDH_DIRECT: + length = insECDH_direct(apdu); + break; case INS_ECDSA: length = insECDSA(apdu); break; @@ -358,6 +362,26 @@ public class ECTesterApplet extends Applet implements ExtendedLength { } /** + * + * @param apdu P1 = byte privkey (KEYPAIR_*) + * @return P2 = byte export (EXPORT_TRUE || EXPORT_FALSE) + * DATA = short corruption (EC_Consts.CORRUPTION_* | ...) + * byte type (EC_Consts.KA_* | ...) + * short length + * byte[] pubkey + */ + private short insECDH_direct(APDU apdu) { + byte privkey = apduArray[ISO7816.OFFSET_P1]; + byte export = apduArray[ISO7816.OFFSET_P2]; + short cdata = apdu.getOffsetCdata(); + short corruption = Util.getShort(apduArray, cdata); + byte type = apduArray[(short) (cdata + 2)]; + short length = Util.getShort(apduArray, (short) (cdata + 3)); + + return ecdh_direct(privkey, export, corruption, type, (short) (cdata + 5), length, apdu.getBuffer(), (short) 0); + } + + /** * Performs ECDSA signature and verification on data provided or random, using the keyPair in P1(local/remote). * returns ecdsa SW, {@code if(export == EXPORT_TRUE)} => short signature_length, byte[] signature * @@ -581,6 +605,41 @@ public class ECTesterApplet extends Applet implements ExtendedLength { return length; } + private short ecdh_direct(byte privkey, byte export, short corruption, byte type, short keyOffset, short keyLength, byte[] outBuffer, short outOffset) { + short length = 0; + + KeyPair priv = ((privkey & KEYPAIR_LOCAL) != 0) ? localKeypair : remoteKeypair; + + short secretLength = 0; + switch (type) { + case EC_Consts.KA_ECDH: + secretLength = keyTester.testECDH_direct(priv, apduArray, keyOffset, keyLength, outBuffer, outOffset, corruption); + break; + case EC_Consts.KA_ECDHC: + secretLength = keyTester.testECDHC_direct(priv, apduArray, keyOffset, keyLength, outBuffer, outOffset, corruption); + break; + case EC_Consts.KA_BOTH: + secretLength = keyTester.testBOTH_direct(priv, apduArray, keyOffset, keyLength, outBuffer, outOffset, corruption); + break; + case EC_Consts.KA_ANY: + secretLength = keyTester.testANY_direct(priv, apduArray, keyOffset, keyLength, outBuffer, outOffset, corruption); + break; + default: + ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); + } + + Util.setShort(outBuffer, outOffset, keyTester.getSW()); + length += 2; + + if ((export == EXPORT_TRUE)) { + Util.setShort(outBuffer, (short) (outOffset + length), secretLength); + length += 2; + Util.arrayCopyNonAtomic(ramArray2, (short) 0, outBuffer, (short) (outOffset + length), secretLength); + length += secretLength; + } + return length; + } + /** * @param sign keyPair to use for signing and verification * @param export whether to export ECDSA signature diff --git a/src/cz/crcs/ectester/applet/EC_Consts.java b/src/cz/crcs/ectester/applet/EC_Consts.java index 53eab41..04cd55e 100644 --- a/src/cz/crcs/ectester/applet/EC_Consts.java +++ b/src/cz/crcs/ectester/applet/EC_Consts.java @@ -68,6 +68,45 @@ public class EC_Consts { public static RandomData randomData = null; + // secp112r1 + public static final byte[] EC112_FP_P = new byte[]{ + (byte) 0xdb, (byte) 0x7c, (byte) 0x2a, (byte) 0xbf, + (byte) 0x62, (byte) 0xe3, (byte) 0x5e, (byte) 0x66, + (byte) 0x80, (byte) 0x76, (byte) 0xbe, (byte) 0xad, + (byte) 0x20, (byte) 0x8b}; + + public static final byte[] EC112_FP_A = new byte[]{ + (byte) 0xdb, (byte) 0x7c, (byte) 0x2a, (byte) 0xbf, + (byte) 0x62, (byte) 0xe3, (byte) 0x5e, (byte) 0x66, + (byte) 0x80, (byte) 0x76, (byte) 0xbe, (byte) 0xad, + (byte) 0x20, (byte) 0x88}; + + public static final byte[] EC112_FP_B = new byte[]{ + (byte) 0x65, (byte) 0x9e, (byte) 0xf8, (byte) 0xba, + (byte) 0x04, (byte) 0x39, (byte) 0x16, (byte) 0xee, + (byte) 0xde, (byte) 0x89, (byte) 0x11, (byte) 0x70, + (byte) 0x2b, (byte) 0x22}; + + public static final byte[] EC112_FP_G_X = new byte[]{ + (byte) 0x09, (byte) 0x48, (byte) 0x72, (byte) 0x39, + (byte) 0x99, (byte) 0x5a, (byte) 0x5e, (byte) 0xe7, + (byte) 0x6b, (byte) 0x55, (byte) 0xf9, (byte) 0xc2, + (byte) 0xf0, (byte) 0x98}; + + public static final byte[] EC112_FP_G_Y = new byte[]{ + (byte) 0xa8, (byte) 0x9c, (byte) 0xe5, (byte) 0xaf, + (byte) 0x87, (byte) 0x24, (byte) 0xc0, (byte) 0xa2, + (byte) 0x3e, (byte) 0x0e, (byte) 0x0f, (byte) 0xf7, + (byte) 0x75, (byte) 0x00}; + + public static final byte[] EC112_FP_R = new byte[]{ + (byte) 0xdb, (byte) 0x7c, (byte) 0x2a, (byte) 0xbf, + (byte) 0x62, (byte) 0xe3, (byte) 0x5e, (byte) 0x76, + (byte) 0x28, (byte) 0xdf, (byte) 0xac, (byte) 0x65, + (byte) 0x61, (byte) 0xc5}; + + public static final short EC112_FP_K = 1; + // secp128r1 from http://www.secg.org/sec2-v2.pdf public static final byte[] EC128_FP_P = new byte[]{ @@ -971,31 +1010,34 @@ public class EC_Consts { public static final byte CURVE_external = (byte) 0xff; // SECP recommended curves over FP - public static final byte CURVE_secp128r1 = (byte) 1; - public static final byte CURVE_secp160r1 = (byte) 2; - public static final byte CURVE_secp192r1 = (byte) 3; - public static final byte CURVE_secp224r1 = (byte) 4; - public static final byte CURVE_secp256r1 = (byte) 5; - public static final byte CURVE_secp384r1 = (byte) 6; - public static final byte CURVE_secp521r1 = (byte) 7; + public static final byte CURVE_secp112r1 = (byte) 1; + public static final byte CURVE_secp128r1 = (byte) 2; + public static final byte CURVE_secp160r1 = (byte) 3; + public static final byte CURVE_secp192r1 = (byte) 4; + public static final byte CURVE_secp224r1 = (byte) 5; + public static final byte CURVE_secp256r1 = (byte) 6; + public static final byte CURVE_secp384r1 = (byte) 7; + public static final byte CURVE_secp521r1 = (byte) 8; - public static final byte FP_CURVES = (byte) 7; + public static final byte FP_CURVES = (byte) 8; // SECP recommended curves over F2M - public static final byte CURVE_sect163r1 = (byte) 8; - public static final byte CURVE_sect233r1 = (byte) 9; - public static final byte CURVE_sect283r1 = (byte) 10; - public static final byte CURVE_sect409r1 = (byte) 11; - public static final byte CURVE_sect571r1 = (byte) 12; + public static final byte CURVE_sect163r1 = (byte) 9; + public static final byte CURVE_sect233r1 = (byte) 10; + public static final byte CURVE_sect283r1 = (byte) 11; + public static final byte CURVE_sect409r1 = (byte) 12; + public static final byte CURVE_sect571r1 = (byte) 13; - public static final byte F2M_CURVES = (byte) 12; + public static final byte F2M_CURVES = (byte) 13; - public static final short[] FP_SIZES = new short[]{112, 128, 160, 192, 224, 256, 384, 512, 521}; + 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}; public static byte getCurve(short keyLength, byte keyClass) { if (keyClass == KeyPair.ALG_EC_FP) { switch (keyLength) { + case (short) 112: + return CURVE_secp112r1; case (short) 128: return CURVE_secp128r1; case (short) 160: @@ -1037,6 +1079,19 @@ public class EC_Consts { public static short getCurveParameter(byte curve, short param, byte[] outputBuffer, short outputOffset) { byte alg = getCurveType(curve); switch (curve) { + case CURVE_secp112r1: { + EC_FP_P = EC112_FP_P; + EC_A = EC112_FP_A; + EC_B = EC112_FP_B; + EC_G_X = EC112_FP_G_X; + EC_G_Y = EC112_FP_G_Y; + EC_R = EC112_FP_R; + EC_K = EC112_FP_K; + EC_W_X = null; + EC_W_Y = null; + EC_S = null; + break; + } case CURVE_secp128r1: { EC_FP_P = EC128_FP_P; EC_A = EC128_FP_A; diff --git a/src/cz/crcs/ectester/reader/Command.java b/src/cz/crcs/ectester/reader/Command.java index 6c2b769..5b7be01 100644 --- a/src/cz/crcs/ectester/reader/Command.java +++ b/src/cz/crcs/ectester/reader/Command.java @@ -429,6 +429,41 @@ public abstract class Command { } } + /** + * + */ + public static class ECDH_direct extends Command { + private byte privkey; + private byte export; + private short corruption; + private byte type; + private byte[] pubkey; + + protected ECDH_direct(CardMngr cardManager, byte privkey, byte export, short corruption, byte type, byte[] pubkey) { + super(cardManager); + this.privkey = privkey; + this.export = export; + this.corruption = corruption; + this.type = type; + this.pubkey = pubkey; + + byte[] data = new byte[3 + pubkey.length]; + Util.setShort(data, 0, corruption); + data[2] = type; + System.arraycopy(pubkey, 0, data, 3, pubkey.length); + + this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDH_DIRECT, privkey, export, data); + } + + @Override + public Response.ECDH send() throws CardException { + long elapsed = -System.nanoTime(); + ResponseAPDU response = cardManager.send(cmd); + elapsed += System.nanoTime(); + return new Response.ECDH(response, elapsed, ECTesterApplet.KEYPAIR_REMOTE, privkey, export, corruption, type); + } + } + public static class ECDSA extends Command { private byte keyPair; private byte export; diff --git a/src/cz/crcs/ectester/reader/TestSuite.java b/src/cz/crcs/ectester/reader/TestSuite.java index 958c51d..7118dd8 100644 --- a/src/cz/crcs/ectester/reader/TestSuite.java +++ b/src/cz/crcs/ectester/reader/TestSuite.java @@ -232,8 +232,11 @@ public abstract class TestSuite { tests.add(new Test(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Test.Result.SUCCESS)); tests.add(new Test(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Test.Result.ANY)); tests.add(new Test(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL), Test.Result.ANY)); - tests.add(new Test(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, key.getParams(), key.flatten()), Test.Result.ANY)); - tests.add(new Test(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ECDH), Test.Result.FAILURE)); + + //tests.add(new Test(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, key.getParams(), key.flatten()), Test.Result.ANY)); + //tests.add(new Test(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ECDH), Test.Result.FAILURE)); + tests.add(new Test(new Command.ECDH_direct(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ECDH, key.flatten()), Test.Result.FAILURE)); + tests.add(new Test(new Command.Cleanup(cardManager), Test.Result.ANY)); } } @@ -277,8 +280,9 @@ public abstract class TestSuite { tests.add(new Test(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Test.Result.SUCCESS)); tests.add(new Test(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL), Test.Result.SUCCESS)); for (EC_Key.Public pub : keys) { - tests.add(new Test(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Test.Result.ANY)); - tests.add(new Test(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ANY), Test.Result.FAILURE)); + // tests.add(new Test(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Test.Result.ANY)); + // tests.add(new Test(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ANY), Test.Result.FAILURE)); + tests.add(new Test(new Command.ECDH_direct(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ANY, pub.flatten()), Test.Result.FAILURE)); } tests.add(new Test(new Command.Cleanup(cardManager), Test.Result.ANY)); } |
