diff options
7 files changed, 604 insertions, 0 deletions
diff --git a/src/cz/crcs/ectester/common/ec/CustomECFieldF2m.java b/src/cz/crcs/ectester/common/ec/CustomECFieldF2m.java new file mode 100644 index 0000000..24ea5aa --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/CustomECFieldF2m.java @@ -0,0 +1,67 @@ +package cz.crcs.ectester.common.ec; + +import java.math.BigInteger; +import java.security.spec.ECFieldF2m; +import java.util.Arrays; + +/** + * @author David Hofman + */ +public class CustomECFieldF2m extends ECFieldF2m { + private int m; + private int[] ks; + private BigInteger rp; + + public CustomECFieldF2m(int m, int[] ks) { + //feed the constructor of the superclass some default, valid data + //getters will return custom parameters instead + super(163, new int[] {3, 2, 1}); + this.m = m; + this.ks = ks.clone(); + + //causes ArithmeticException if m < 0 or any element of ks < 0 + this.rp = BigInteger.ONE; + this.rp = this.rp.setBit(m); + for(int i = 0; i < this.ks.length; ++i) { + this.rp = this.rp.setBit(this.ks[i]); + } + } + + @Override + public int getFieldSize() { + return m; + } + + @Override + public int getM() { + return m; + } + + @Override + public int[] getMidTermsOfReductionPolynomial() { + return ks.clone(); + } + + @Override + public BigInteger getReductionPolynomial() { + return rp; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (!(o instanceof CustomECFieldF2m)) { + return false; + } else { + return m == ((CustomECFieldF2m) o).m && Arrays.equals(ks, ((CustomECFieldF2m) o).ks); + } + } + + @Override + public int hashCode() { + int hash = m << 5; + hash += rp == null ? 0 : rp.hashCode(); + return hash; + } +} diff --git a/src/cz/crcs/ectester/common/ec/CustomECFieldFp.java b/src/cz/crcs/ectester/common/ec/CustomECFieldFp.java new file mode 100644 index 0000000..eafcb72 --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/CustomECFieldFp.java @@ -0,0 +1,43 @@ +package cz.crcs.ectester.common.ec; + +import java.math.BigInteger; +import java.security.spec.ECFieldFp; + +/** + * @author David Hofman + */ +public class CustomECFieldFp extends ECFieldFp { + private BigInteger p; + + public CustomECFieldFp(BigInteger p) { + //feed the constructor of the superclass some default, valid parameter p + //getters will return custom (and possibly invalid) data + super(BigInteger.ONE); + this.p = p; + } + + + @Override + public int getFieldSize() { + return p.bitCount(); + } + + @Override + public BigInteger getP() { + return p; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else { + return o instanceof CustomECFieldFp && p.equals(((CustomECFieldFp) o).p); + } + } + + @Override + public int hashCode() { + return p.hashCode(); + } +} diff --git a/src/cz/crcs/ectester/common/ec/CustomECParameterSpec.java b/src/cz/crcs/ectester/common/ec/CustomECParameterSpec.java new file mode 100644 index 0000000..cbc15e7 --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/CustomECParameterSpec.java @@ -0,0 +1,47 @@ +package cz.crcs.ectester.common.ec; + +import java.math.BigInteger; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.EllipticCurve; + +/** + * @author David Hofman + */ +public class CustomECParameterSpec extends ECParameterSpec { + private EllipticCurve curve; + private ECPoint g; + private BigInteger n; + private int h; + + public CustomECParameterSpec(EllipticCurve curve, ECPoint g, BigInteger n, int h) { + //feed the constructor of the superclass some default, valid data + //getters will return custom (and possibly invalid) parameters instead + super(new EllipticCurve(new ECFieldFp(BigInteger.ONE),BigInteger.ZERO,BigInteger.ZERO), new ECPoint(BigInteger.ZERO, BigInteger.ZERO), BigInteger.ONE, 1); + this.curve = curve; + this.g = g; + this.n = n; + this.h = h; + } + + @Override + public EllipticCurve getCurve() { + return curve; + } + + @Override + public ECPoint getGenerator() { + return g; + } + + @Override + public BigInteger getOrder() { + return n; + } + + @Override + public int getCofactor() { + return h; + } +} diff --git a/src/cz/crcs/ectester/common/ec/CustomEllipticCurve.java b/src/cz/crcs/ectester/common/ec/CustomEllipticCurve.java new file mode 100644 index 0000000..489861c --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/CustomEllipticCurve.java @@ -0,0 +1,60 @@ +package cz.crcs.ectester.common.ec; + +import java.math.BigInteger; +import java.security.spec.ECField; +import java.security.spec.ECFieldFp; +import java.security.spec.EllipticCurve; + +/** + * @author David Hofman + */ +public class CustomEllipticCurve extends EllipticCurve { + private ECField field; + private BigInteger a; + private BigInteger b; + + public CustomEllipticCurve(ECField field, BigInteger a, BigInteger b) { + //feed the constructor of the superclass some default, valid EC parameters + //getters will return custom (and possibly invalid) data instead + super(new ECFieldFp(BigInteger.ONE), BigInteger.ZERO, BigInteger.ZERO); + this.field = field; + this.a = a; + this.b = b; + + } + + @Override + public BigInteger getA() { + return a; + } + + @Override + public BigInteger getB() { + return b; + } + + @Override + public ECField getField() { + return field; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else { + if (o instanceof CustomEllipticCurve) { + CustomEllipticCurve otherCurve = (CustomEllipticCurve) o; + if (field.equals(otherCurve.field) && a.equals(otherCurve.a) && b.equals(otherCurve.b)) { + return true; + } + } + return false; + } + } + + @Override + public int hashCode() { + return field.hashCode() << 6 + (a.hashCode() << 4) + (b.hashCode() << 2); + } +} diff --git a/src/cz/crcs/ectester/common/ec/EC_Params.java b/src/cz/crcs/ectester/common/ec/EC_Params.java index b08fdfd..e922feb 100644 --- a/src/cz/crcs/ectester/common/ec/EC_Params.java +++ b/src/cz/crcs/ectester/common/ec/EC_Params.java @@ -88,6 +88,45 @@ public class EC_Params extends EC_Data { return result; } + public boolean setParam(short param, byte[][] value) { + if (!hasParam(param)) { + return false; + } + if (Integer.bitCount(param) != 1) { + return false; + } + short paramMask = EC_Consts.PARAMETER_FP; + int i = 0; + while (paramMask <= EC_Consts.PARAMETER_S) { + short masked = (short) (this.params & param & paramMask); + short shallow = (short) (this.params & paramMask); + if (masked != 0) { + if (masked == EC_Consts.PARAMETER_F2M) { + data[i] = value[0]; + data[i + 1] = value[1]; + data[i + 2] = value[2]; + data[i + 3] = value[3]; + break; + } + if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) { + data[i] = value[0]; + data[i + 1] = value[1]; + break; + } + data[i] = value[0]; + } + if (shallow == EC_Consts.PARAMETER_F2M) { + i += 4; + } else if (shallow == EC_Consts.PARAMETER_G || shallow == EC_Consts.PARAMETER_W) { + i += 2; + } else if (shallow != 0) { + i++; + } + paramMask = (short) (paramMask << 1); + } + return true; + } + public boolean hasParam(short param) { return (params & param) != 0; } diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java index 637152a..034dbc5 100644 --- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -314,6 +314,7 @@ public class ECTesterStandalone { new StandaloneDefaultSuite(null, null, null), new StandaloneTestVectorSuite(null, null, null), new StandaloneInvalidSuite(null, null, null), + new StandaloneWrongSuite(null, null, null), new StandaloneDegenerateSuite(null, null, null), new StandaloneCofactorSuite(null, null, null), new StandaloneEdgeCasesSuite(null, null, null), @@ -754,6 +755,9 @@ public class ECTesterStandalone { case "test-vectors": suite = new StandaloneTestVectorSuite(writer, cfg, cli); break; + case "wrong": + suite = new StandaloneWrongSuite(writer, cfg, cli); + break; case "degenerate": suite = new StandaloneDegenerateSuite(writer, cfg, cli); break; diff --git a/src/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java new file mode 100644 index 0000000..589c0d7 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java @@ -0,0 +1,344 @@ +package cz.crcs.ectester.standalone.test.suites; + +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.cli.TreeCommandLine; +import cz.crcs.ectester.common.ec.*; +import cz.crcs.ectester.common.output.TestWriter; +import cz.crcs.ectester.common.test.CompoundTest; +import cz.crcs.ectester.common.test.Result; +import cz.crcs.ectester.common.test.Test; +import cz.crcs.ectester.common.util.ByteUtil; +import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.standalone.ECTesterStandalone; +import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; +import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTest; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTest; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable; + +import javax.crypto.KeyAgreement; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.*; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author David Hofman + */ +public class StandaloneWrongSuite extends StandaloneTestSuite { + private KeyAgreement ka; + private KeyPairGenerator kpg; + + public StandaloneWrongSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli) { + super(writer, cfg, cli, "wrong", "The wrong curve suite tests whether the library rejects domain parameters which are not curves.", + "Supports options:", + "\t - gt/kpg-type", + "\t - kt/ka-type", + "\t - skip (place this option before the library name to skip tests that can potentially cause a freeze)"); + } + + + @Override + protected void runTests() throws Exception { + String kpgAlgo = cli.getOptionValue("test.kpg-type"); + String kaAlgo = cli.getOptionValue("test.ka-type"); + boolean skip = cli.getArg(1).equalsIgnoreCase("-skip"); + + KeyPairGeneratorIdent kpgIdent; + if (kpgAlgo == null) { + // try EC, if not, fail with: need to specify kpg algo. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains("EC")) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The default KeyPairGenerator algorithm type of \"EC\" was not found. Need to specify a type."); + return; + } + } else { + // try the specified, if not, fail with: wrong kpg algo/not found. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains(kpgAlgo)) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The KeyPairGenerator algorithm type of \"" + kpgAlgo + "\" was not found."); + return; + } + } + kpg = kpgIdent.getInstance(cfg.selected.getProvider()); + + KeyAgreementIdent kaIdent; + if (kaAlgo == null) { + // try ECDH, if not, fail with: need to specify ka algo. + Optional<KeyAgreementIdent> kaIdentOpt = cfg.selected.getKAs().stream() + .filter((ident) -> ident.contains("ECDH")) + .findFirst(); + if (kaIdentOpt.isPresent()) { + kaIdent = kaIdentOpt.get(); + } else { + System.err.println("The default KeyAgreement algorithm type of \"ECDH\" was not found. Need to specify a type."); + return; + } + } else { + // try the specified, if not, fail with: wrong ka algo/not found. + Optional<KeyAgreementIdent> kaIdentOpt = cfg.selected.getKAs().stream() + .filter((ident) -> ident.contains(kaAlgo)) + .findFirst(); + if (kaIdentOpt.isPresent()) { + kaIdent = kaIdentOpt.get(); + } else { + System.err.println("The KeyAgreement algorithm type of \"" + kaAlgo + "\" was not found."); + return; + } + } + ka = kaIdent.getInstance(cfg.selected.getProvider()); + + /* Just do the default run on the wrong curves. + * These should generally fail, the curves aren't curves. + */ + if(!skip) { + Map<String, EC_Curve> wrongCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "wrong"); + for (Map.Entry<String, EC_Curve> e : wrongCurves.entrySet()) { + + EC_Curve curve = e.getValue(); + ECParameterSpec spec = curve.toSpec(); + String type = curve.getField() == javacard.security.KeyPair.ALG_EC_FP ? "FP" : "F2M"; + + //try generating a keypair + KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + runTest(generate); + KeyPair kp = kgt.getKeyPair(); + if (kp == null) { + Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ".", generate); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Wrong curve test of " + curve.getBits() + + "b " + type + ". " + curve.getDesc(), generateFail)); + continue; + } + Test generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); + ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); + ECPublicKey ecpub = (ECPublicKey) kp.getPublic(); + + KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); + KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub); + Test ecdh = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Wrong curve test of " + curve.getBits() + + "b " + type + ". " + curve.getDesc(), generateSuccess, ecdh)); + } + } + + /* + * Do some interesting tests with corrupting the custom curves. + * For prime field: + * - p = 0 + * - p = 1 + * - p is a square of a prime + * - p is a composite q * s with q, s primes + * - TODO: p divides discriminant + */ + Map<String, EC_Curve> curveMap = EC_Store.getInstance().getObjects(EC_Curve.class, "secg"); + List<EC_Curve> curves = curveMap.entrySet().stream().filter((e) -> e.getKey().endsWith("r1") && + e.getValue().getField() == javacard.security.KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList()); + Random r = new Random(); + for (EC_Curve curve : curves) { + short bits = curve.getBits(); + final byte[] originalp = curve.getParam(EC_Consts.PARAMETER_FP)[0]; + + curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{ ByteUtil.hexToBytes("0")}); + Test prime0 = ecdhTest(toCustomSpec(curve),"ECDH with p = 0."); + + curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{ ByteUtil.hexToBytes("1")}); + Test prime1 = ecdhTest(toCustomSpec(curve),"ECDH with p = 1."); + + short keyHalf = (short) (bits / 2); + BigInteger prime = new BigInteger(keyHalf, 50, r); + BigInteger primePow = prime.pow(2); + byte[] primePowBytes = ECUtil.toByteArray(primePow, bits); + curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{primePowBytes}); + + Test primePower = ecdhTest(toCustomSpec(curve), "ECDH with p = q^2."); + + BigInteger q = new BigInteger(keyHalf, r); + BigInteger s = new BigInteger(keyHalf, r); + BigInteger compositeValue = q.multiply(s); + byte[] compositeBytes = ECUtil.toByteArray(compositeValue, bits); + curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{compositeBytes}); + + Test composite = ecdhTest(toCustomSpec(curve), "ECDH with p = q * s."); + + Test wrongPrime = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted prime parameter.", prime0 , prime1, primePower, composite ); + + curve.setParam(EC_Consts.PARAMETER_FP, new byte[][] {originalp}); + final byte[][] originalG = curve.getParam(EC_Consts.PARAMETER_G); + + byte[] Gx = new BigInteger(curve.getBits(), r).toByteArray(); + byte[] Gy = new BigInteger(curve.getBits(), r).toByteArray(); + curve.setParam(EC_Consts.PARAMETER_G, new byte[][] {Gx, Gy}); + Test fullRandomG = ecdhTest(toCustomSpec(curve), "ECDH with G = random data."); + + final BigInteger originalBigp = new BigInteger(1, originalp); + byte[] smallerGx = new BigInteger(curve.getBits(), r).mod(originalBigp).toByteArray(); + byte[] smallerGy = new BigInteger(curve.getBits(), r).mod(originalBigp).toByteArray(); + curve.setParam(EC_Consts.PARAMETER_G, new byte[][] {smallerGx, smallerGy}); + Test randomG = ecdhTest(toCustomSpec(curve), "ECDH with G = random data mod p."); + + curve.setParam(EC_Consts.PARAMETER_G, new byte[][] {ByteUtil.hexToBytes("0"), ByteUtil.hexToBytes("0")}); + Test zeroG = ecdhTest(toCustomSpec(curve), "ECDH with G = infinity."); + + Test wrongG = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted G parameter.", fullRandomG, randomG, zeroG); + + curve.setParam(EC_Consts.PARAMETER_G, originalG); + final byte[] originalR = curve.getParam(EC_Consts.PARAMETER_R)[0]; + final BigInteger originalBigR = new BigInteger(1, originalR); + + List<Test> allRTests = new LinkedList<>(); + if(!skip) { + byte[] RZero = new byte[]{(byte) 0}; + curve.setParam(EC_Consts.PARAMETER_R, new byte[][]{RZero}); + allRTests.add(ecdhTest(toCustomSpec(curve), "ECDH with R = 0.")); + + + byte[] ROne = new byte[]{(byte) 1}; + curve.setParam(EC_Consts.PARAMETER_R, new byte[][]{ROne}); + allRTests.add(ecdhTest(toCustomSpec(curve), "ECDH with R = 1.")); + } + + BigInteger prevPrimeR; + do { + prevPrimeR = BigInteger.probablePrime(originalBigR.bitLength() - 1, r); + } while (prevPrimeR.compareTo(originalBigR) >= 0); + byte[] prevRBytes = ECUtil.toByteArray(prevPrimeR, bits); + curve.setParam(EC_Consts.PARAMETER_R, new byte[][] {prevRBytes}); + allRTests.add(ecdhTest(toCustomSpec(curve), "ECDH with R = some prime (but [r]G != infinity) smaller than original R.")); + + BigInteger nextPrimeR = originalBigR.nextProbablePrime(); + byte[] nextRBytes = ECUtil.toByteArray(nextPrimeR, bits); + curve.setParam(EC_Consts.PARAMETER_R, new byte[][]{nextRBytes}); + allRTests.add(ecdhTest(toCustomSpec(curve), "ECDH with R = some prime (but [r]G != infinity) larger than original R.")); + + byte[] nonprimeRBytes = nextRBytes.clone(); + nonprimeRBytes[nonprimeRBytes.length - 1] ^= 1; + curve.setParam(EC_Consts.PARAMETER_R, new byte[][] {nonprimeRBytes} ); + allRTests.add(ecdhTest(toCustomSpec(curve), "ECDH with R = some composite (but [r]G != infinity).")); + + Test wrongR = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted R parameter.", allRTests.toArray(new Test[0])); + + curve.setParam(EC_Consts.PARAMETER_R, new byte[][] {originalR}); + + byte[] kRaw = new byte[]{(byte) 0xff}; + curve.setParam(EC_Consts.PARAMETER_K, new byte[][] {kRaw}); + Test bigK = ecdhTest(toCustomSpec(curve), "ECDH with big K."); + + byte[] kZero = new byte[]{(byte) 0}; + curve.setParam(EC_Consts.PARAMETER_K, new byte[][]{kZero}); + Test zeroK = ecdhTest(toCustomSpec(curve), "ECDH with K = 0."); + + Test wrongK = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted K parameter.", bigK, zeroK); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests of " + bits + "b " + "FP", wrongPrime, wrongG, wrongR , wrongK)); + } + + + /* + * For binary field: + * - e1 = e2 = e3 = 0 + * - e1, e2 or e3 is larger than m. + */ + curveMap = EC_Store.getInstance().getObjects(EC_Curve.class, "secg"); + curves = curveMap.entrySet().stream().filter((e) -> e.getKey().endsWith("r1") && + e.getValue().getField() == javacard.security.KeyPair.ALG_EC_F2M).map(Map.Entry::getValue).collect(Collectors.toList()); + for (EC_Curve curve : curves) { + short bits = curve.getBits(); + byte[][] coeffBytes; + + + coeffBytes = new byte[][]{ + ByteUtil.shortToBytes(bits), + ByteUtil.shortToBytes((short) 0), + ByteUtil.shortToBytes((short) 0), + ByteUtil.shortToBytes((short) 0)}; + curve.setParam(EC_Consts.PARAMETER_F2M, coeffBytes); + Test coeff0 = ecdhTest(toCustomSpec(curve), "ECDH with wrong field polynomial: x^"); + + short e1 = (short) (2 * bits); + short e2 = (short) (3 * bits); + short e3 = (short) (4 * bits); + coeffBytes = new byte[][]{ + ByteUtil.shortToBytes(bits), + ByteUtil.shortToBytes(e1), + ByteUtil.shortToBytes(e2), + ByteUtil.shortToBytes(e3)}; + curve.setParam(EC_Consts.PARAMETER_F2M, coeffBytes); + Test coeffLarger = ecdhTest(toCustomSpec(curve), "ECDH with wrong field poly, powers larger than " + bits); + + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted field polynomial parameter over " + curve.getBits() + "b F2M", coeff0, coeffLarger)); + } + } + + private Test ecdhTest(ECParameterSpec spec, String desc) { + //generate KeyPair + KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.FAILURE); + runTest(generate); + KeyPair kp = kgt.getKeyPair(); + if(kp == null) { + return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, generate); + } + ECPublicKey pub = (ECPublicKey) kp.getPublic(); + ECPrivateKey priv = (ECPrivateKey) kp.getPrivate(); + + //perform ECDH + KeyAgreementTestable testable = new KeyAgreementTestable(ka, priv, pub); + Test ecdh = KeyAgreementTest.expect(testable, Result.ExpectedValue.FAILURE); + return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, generate, ecdh); + } + + //constructs EllipticCurve from EC_Curve even if the parameters of the curve are wrong + private EllipticCurve toCustomCurve(EC_Curve curve) { + ECField field; + if (curve.getField() == javacard.security.KeyPair.ALG_EC_FP) { + field = new CustomECFieldFp(new BigInteger(1, curve.getData(0))); + } else { + byte[][] fieldData = curve.getParam(EC_Consts.PARAMETER_F2M); + int m = ByteUtil.getShort(fieldData[0], 0); + int e1 = ByteUtil.getShort(fieldData[1], 0); + int e2 = ByteUtil.getShort(fieldData[2], 0); + int e3 = ByteUtil.getShort(fieldData[3], 0); + int[] powers; + if (e2 == 0 && e3 == 0) { + powers = new int[]{e1}; + } else { + powers = new int[]{e1, e2, e3}; + } + field = new CustomECFieldF2m(m, powers); + } + + BigInteger a = new BigInteger(1, curve.getParam(EC_Consts.PARAMETER_A)[0]); + BigInteger b = new BigInteger(1, curve.getParam(EC_Consts.PARAMETER_B)[0]); + + return new CustomEllipticCurve(field, a, b); + } + + //constructs ECParameterSpec from EC_Curve even if the parameters of the curve are wrong + private ECParameterSpec toCustomSpec(EC_Curve curve) { + EllipticCurve customCurve = toCustomCurve(curve); + + byte[][] G = curve.getParam(EC_Consts.PARAMETER_G); + BigInteger gx = new BigInteger(1, G[0]); + BigInteger gy = new BigInteger(1, G[1]); + ECPoint generator = new ECPoint(gx, gy); + + BigInteger n = new BigInteger(1, curve.getParam(EC_Consts.PARAMETER_R)[0]); + + int h = new BigInteger(1, curve.getParam(EC_Consts.PARAMETER_K)[0]).intValue(); + return new CustomECParameterSpec(customCurve, generator, n, h); + } +} |
