From 370f65c33992f71b7d21296f0fe44fa1380d4541 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 4 Feb 2018 19:20:08 +0100 Subject: Update README, docs and test suites. --- docs/CURVES.md | 44 +++++++++++++++++++++++++------------ docs/LIBS.md | 4 +--- docs/TESTS.md | 68 +++++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 75 insertions(+), 41 deletions(-) (limited to 'docs') diff --git a/docs/CURVES.md b/docs/CURVES.md index 4a80d49..a04e82f 100644 --- a/docs/CURVES.md +++ b/docs/CURVES.md @@ -1,47 +1,63 @@ # Curves +ECTester contains a collection of elliptic curve/point parameters, these parameters either come from standards or +were generated manually or using [ecgen](https://github.com/J08nY/ecgen). -## SECG +These parameters can be found in the [cz.crcs.ectester.data](/src/cz/ectester/data/) package. + + +## Standard + +### SECG SEC 2: Recommended Elliptic Curve Domain Parameters version 2.0 January 27, 2010 [Source](http://www.secg.org/sec2-v2.pdf) -## NIST +### NIST RECOMMENDED ELLIPTIC CURVES FOR FEDERAL GOVERNMENT USE July 1999 [Source](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf) -## x962 +### x962 ANSI X9.62 example curves. -## Brainpool +### Brainpool ECC Brainpool Standard Curves and Curve Generation v. 1.0 19.10.2005 [Source](http://www.ecc-brainpool.org/download/Domain-parameters.pdf) -## anssi +### anssi Agence nationale de la sécurité des systèmes d'information: Publication d'un paramétrage de courbe elliptique visant des applications de passeport électronique et de l'administration électronique française. 21 November 2011 -## GOST +### GOST GOST R 34.10-2001: RFC5832 curves. [Source](https://tools.ietf.org/html/rfc5832) -## anomalous + +## Generated + +### anomalous These prime field curves have the same order as the field order, and are susceptible to attacks reducing ECDLP over a multiplicative group of the curve, to DLP over an additive group of the underlying field, which is easy (linear time). Some of these are from Atsuko Miyaji's [paper](https://dspace.jaist.ac.jp/dspace/bitstream/10119/4464/1/73-61.pdf), others were generated using [ecgen](htps://github.com/J08nY/ecgen). -## invalid +### invalid This category contains pre-generated invalid curves for a large subset of NIST, SECG and Brainpool curves. Invalid curves for a given curve, are short Weierstrass curves with all parameters equal to the given curve except the `b` parameter. These curves can be used to [attack some implementations](https://www.nds.rub.de/media/nds/veroeffentlichungen/2015/09/14/main-full.pdf). -Generated using [ecgen](https://github.com/J08nY/ecgen) +Generated using [ecgen](https://github.com/J08nY/ecgen). -## composite +### composite Contains curves of composite order, with small order points. -Generated using [ecgen](https://github.com/J08nY/ecgen) +Generated using [ecgen](https://github.com/J08nY/ecgen). + +### wrong +Contains parameters that are not elliptic curves(over Fp and F2m), such as `p` parameter that is not prime or an irreducible polynomial that is not irreducible. + +Generated manually. -## wrong -Contains parameters that are not elliptic curves(over Fp and F2m), such as `p` parameter that is not prime, irreducible polynomial that is not irreducible and similar. +### twist +Contains pre-generated points on twists of known named curves from NIST, SECG. +These points can be used to attack some implementations. -Generated manually. \ No newline at end of file +Generated using [ecgen](https://github.com/J08nY/ecgen). \ No newline at end of file diff --git a/docs/LIBS.md b/docs/LIBS.md index 4fac57b..1f1f92c 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -1,15 +1,13 @@ -# Libraries with ECC +# Libraries with ECC support Libraries with at least some ECC support: - [Crypto++](https://cryptopp.com/) - [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/) - - [mbedTLS](https://tls.mbed.org/) - [Nettle](http://www.lysator.liu.se/~nisse/nettle/) - [OpenSSL](https://www.openssl.org/) - [OpenSSL (FIPS mode)](https://www.openssl.org/docs/fipsnotes.html) - - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) - [Microsoft .NET crypto](https://docs.microsoft.com/en-us/dotnet/standard/security/cryptography-model) diff --git a/docs/TESTS.md b/docs/TESTS.md index c4f38dc..72c328d 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -1,12 +1,13 @@ -# Tests +# Test suites - `default` - `test-vectors` - `wrong` - `composite` - `invalid` + - `twist` -**NOTE: The `wrong`, `composite` and `invalid` test suites caused temporary DoS of some cards. These test suites prompt you for +**NOTE: The `wrong`, `composite`, `invalid` and `twist` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for confirmation before running, be cautious.** ## Default @@ -18,14 +19,10 @@ This test suite is run if no argument is provided to `-t / --test`. For example: ```bash -java -jar ECTester.jar -a -fp -t +java -jar ECTester.jar -t ``` -tests all(`-a`), prime field(`-fp`), using the default test suite. +tests prime field and binary field curves, using the default test suite. -```bash -java -jar ECTester.jar-a -f2m -t -``` -tests all(`-a`), binary field(`-f2m`), curves. ## Test-Vectors Tests using known test vectors provided by NIST/SECG/Brainpool: @@ -40,25 +37,33 @@ Tests using known test vectors provided by NIST/SECG/Brainpool: For example: ```bash -java -jar ECTester.jar -t test-vectors -nc nist -a -f2m -``` -tests all(`-a`), binary field(`-f2m`) NIST curves for which test-vectors are provided. Although this test suite is better for general testing: -```bash -java -jar ECTester.jar -t test-vectors -a +java -jar ECTester.jar -t test-vectors ``` +tests all curves for which test-vectors are provided. + + ## Wrong -Tests using the default tests on a category of wrong curves. These curves are not really curves as they have: +Tests on a category of wrong curves. These curves are not really curves as they have: - non-prime field in the prime-field case - reducible polynomial as the field polynomial in the binary case +This test suite also does some additional tests with corrupting the field parameter: + - Fp: + - p = 0 + - p = 1 + - p = q^2; q prime + - p = q * s; q and s prime + - F2m: + - e1 = e2 = e3 = 0 + - m < e1 < e2 < e3 + +These tests should fail generally. -These tests should fail generally. They are equivalent with `java -jar ECTester.jar -nc wrong -t`, the default tests over the `wrong` category -of curves. - For example: ```bash -java -jar ECTester.jar -t wrong -b 521 -fp +java -jar ECTester.jar -t wrong ``` -tests a 521 bit(`-b`), prime-field(`-fp`) wrong curve. +does all wrong curve tests. + ## Composite Tests using curves that don't have a prime order/nearly prime order. @@ -67,16 +72,31 @@ by the applet. Operations over such curves are susceptible to small-subgroup att For example: ```bash -java -jar ECTester.jar -t composite -b 160 -fp +java -jar ECTester.jar -t composite ``` + ## Invalid -Tests using known named curves from several categories(SECG/NIST/Brainpool) against pregenerated *invalid* public keys. -These tests should definitely fail, a success here implies the card is susceptible to invalid curve attacks. +Tests using known named curves from several categories(SECG/NIST/Brainpool) against pre-generated *invalid* public keys. +ECDH should definitely fail, a success here implies the card is susceptible to invalid curve attacks. +See [Practical Invalid Curve Attacks on TLS-ECDH](https://www.nds.rub.de/media/nds/veroeffentlichungen/2015/09/14/main-full.pdf) for more information. For example: ```bash -java -jar ECTester.jar -t invalid -nc nist -a -fp +java -jar ECTester.jar -t invalid ``` -tests using all(`-a`), prime-field(`-fp`) NIST curves and pregenerated *invalid* public keys for these curves. \ No newline at end of file +tests using all curves with pregenerated *invalid* public keys for these curves. + + +## Twist +Tests using known named curves froms several categories(SECG/NIST) against pre-generated points on twists of said curves. +ECDH should fail, a success here implies the card is not twist secure, if a curve with an unsecure twist is used, +the card might compute on the twist, if a point on the twist is supplied. + +See [SafeCurves on twist security](https://safecurves.cr.yp.to/twist.html) for more information. + +For example: +```bash +java -jar ECTester.jar -t twist +``` \ No newline at end of file -- cgit v1.3.1 From 30e29e6244aad9e28aacb187d6e2bc1f44ed322c Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Mar 2018 20:03:04 +0100 Subject: Add information about more output files for a test run. --- README.md | 19 +++++++++++++++++-- docs/FORMAT.md | 6 +++++- .../crcs/ectester/reader/output/FileTestWriter.java | 1 - 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 1af8a21..c34da5d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build status](https://api.travis-ci.org/crocs-muni/ECTester.svg?branch=master)](https://travis-ci.org/crocs-muni/ECTester) [![GitHub release](https://img.shields.io/github/release/crocs-muni/ECTEster.svg)](https://github.com/crocs-muni/ECTester/releases) [![license](https://img.shields.io/github/license/crocs-muni/ECTester.svg)](https://github.com/crocs-muni/ECTester/blob/master/LICENSE) [![docs](https://img.shields.io/badge/docs-github.io-brightgreen.svg)](https://crocs-muni.github.io/ECTester/) Tests support and behavior of elliptic curve cryptography implementations on JavaCards (`TYPE_EC_FP` and `TYPE_EC_F2M`) and on selected software libraries. -For more information on ECC support on JavaCards see the [github page](https://crocs-muni.github.io/ECTester/). +For more information on ECC support on JavaCards see the [github page](https://crocs-muni.github.io/ECTester/), with results, tables and docs. ## Build @@ -106,6 +106,8 @@ For format of this file see [FORMAT](docs/FORMAT.md). Perform support and performance tests of ECC. +Use with `-o / --output [out_type:]` to output the test results to a file. +For possible formats of this file see [FORMAT](docs/FORMAT.md). For more info about the test suites see [TESTS](docs/TESTS.md). #### Generate @@ -206,6 +208,19 @@ Currently supported libraries include: For more information on ECC libraries see [LIBS](docs/LIBS.md). +### Setup + +Installing the Java Cryptography Extension Unlimited Strength policy files is necessary to do testing +with quite a lot of practical key sizes, they are available for download: + + * [Java 6](http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html) + * [Java 7](http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html) + * [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) + +To install, place them in `${java.home}/jre/lib/security/`. + +### Options + ``` usage: ECTesterStandalone.jar [-V] [-h] [ (ecdh [-t ] [-n ] [-b ] [-nc ]) | (ecdsa [-t ] [-n ] [-b ] [-nc ] [-f ]) | @@ -251,5 +266,5 @@ usage: ECTesterStandalone.jar [-V] [-h] [ (ecdh [-t ] [-n ] [-b Set the Signature object [type]. -b,--bits What size of curve to use. -nc,--named-curve Use a named curve, from CurveDB: +``` -``` \ No newline at end of file diff --git a/docs/FORMAT.md b/docs/FORMAT.md index 849a62c..bde2543 100644 --- a/docs/FORMAT.md +++ b/docs/FORMAT.md @@ -56,4 +56,8 @@ Output of the `-dsa/--ecdsa` option. ## Test runs By default test runs are output in a human readable format, however YAML and XML is also supported and can be selected -by using the `-o/--output` option. +by using the `--format` option. Also, prefixing the output file name when using the `-o/--output` option allows to output +the same test run in different formats to different files. + +For example: +`--format yaml -o default_output.yaml -o xml:output_file.xml -o text:readable_text_file.txt ` diff --git a/src/cz/crcs/ectester/reader/output/FileTestWriter.java b/src/cz/crcs/ectester/reader/output/FileTestWriter.java index 6cfece1..e4ef9b8 100644 --- a/src/cz/crcs/ectester/reader/output/FileTestWriter.java +++ b/src/cz/crcs/ectester/reader/output/FileTestWriter.java @@ -19,7 +19,6 @@ public class FileTestWriter extends TeeTestWriter { public FileTestWriter(String defaultFormat, boolean systemOut, String[] files) throws ParserConfigurationException, FileNotFoundException { int fLength = files == null ? 0 : files.length; writers = new TestWriter[systemOut ? fLength + 1 : fLength]; - System.err.println(writers.length); if (systemOut) { writers[0] = createWriter(defaultFormat, System.out); } -- cgit v1.3.1 From 510116dd24fdd2e676d405eeede5309acef903f9 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 3 Mar 2018 23:14:08 +0100 Subject: Add Cofactor test suite. --- docs/CURVES.md | 5 ++ docs/TESTS.md | 12 ++++- src/cz/crcs/ectester/reader/ECTesterReader.java | 7 ++- .../reader/test/CardCofactorTestSuite.java | 60 ++++++++++++++++++++++ 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java (limited to 'docs') diff --git a/docs/CURVES.md b/docs/CURVES.md index a04e82f..a815c5c 100644 --- a/docs/CURVES.md +++ b/docs/CURVES.md @@ -60,4 +60,9 @@ Generated manually. Contains pre-generated points on twists of known named curves from NIST, SECG. These points can be used to attack some implementations. +Generated using [ecgen](https://github.com/J08nY/ecgen). + +### cofactor +Contains curves that are composite order, with points not on the subgroup generated by the generator. + Generated using [ecgen](https://github.com/J08nY/ecgen). \ No newline at end of file diff --git a/docs/TESTS.md b/docs/TESTS.md index 72c328d..8f8fa2e 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -6,8 +6,9 @@ - `composite` - `invalid` - `twist` + - `cofactor` -**NOTE: The `wrong`, `composite`, `invalid` and `twist` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for +**NOTE: The `wrong`, `composite`, `invalid`,`twist` and `cofactor` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for confirmation before running, be cautious.** ## Default @@ -99,4 +100,13 @@ See [SafeCurves on twist security](https://safecurves.cr.yp.to/twist.html) for m For example: ```bash java -jar ECTester.jar -t twist +``` + +## Cofactor +Tests whether the card correctly rejects points that lie on the curve but not on the subgroup generated by the specified generator +during ECDH. + +For example: +```bash +java -jar ECTester.jar -t cofactor ``` \ No newline at end of file diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java index 9c80bd2..1e8b8a4 100644 --- a/src/cz/crcs/ectester/reader/ECTesterReader.java +++ b/src/cz/crcs/ectester/reader/ECTesterReader.java @@ -246,7 +246,7 @@ public class ECTesterReader { actions.addOption(Option.builder("ln").longOpt("list-named").desc("Print the list of supported named curves and keys.").hasArg().argName("what").optionalArg(true).build()); actions.addOption(Option.builder("e").longOpt("export").desc("Export the defaut curve parameters of the card(if any).").build()); actions.addOption(Option.builder("g").longOpt("generate").desc("Generate [amount] of EC keys.").hasArg().argName("amount").optionalArg(true).build()); - actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. [test_suite]:\n- default:\n- invalid:\n- twist:\n- wrong:\n- composite:\n- test-vectors:").hasArg().argName("test_suite").optionalArg(true).build()); + actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. [test_suite]:\n- default:\n- invalid:\n- twist:\n- cofactor:\n- wrong:\n- composite:\n- test-vectors:").hasArg().argName("test_suite").optionalArg(true).build()); actions.addOption(Option.builder("dh").longOpt("ecdh").desc("Do EC KeyAgreement (ECDH...), [count] times.").hasArg().argName("count").optionalArg(true).build()); actions.addOption(Option.builder("dsa").longOpt("ecdsa").desc("Sign data with ECDSA, [count] times.").hasArg().argName("count").optionalArg(true).build()); @@ -431,6 +431,9 @@ public class ECTesterReader { case "twist": suite = new CardTwistTestSuite(writer, cfg, cardManager); break; + case "cofactor": + suite = new CardCofactorTestSuite(writer, cfg, cardManager); + break; default: System.err.println("Unknown test suite."); return; @@ -760,7 +763,7 @@ public class ECTesterReader { } testSuite = cli.getOptionValue("test", "default").toLowerCase(); - String[] tests = new String[]{"default", "composite", "invalid", "test-vectors", "wrong", "twist"}; + String[] tests = new String[]{"default", "composite", "invalid", "test-vectors", "wrong", "twist", "cofactor"}; if (!Arrays.asList(tests).contains(testSuite)) { System.err.println("Unknown test suite " + testSuite + ". Should be one of: " + Arrays.toString(tests)); return false; diff --git a/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java b/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java new file mode 100644 index 0000000..d3aef3a --- /dev/null +++ b/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java @@ -0,0 +1,60 @@ +package cz.crcs.ectester.reader.test; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Curve; +import cz.crcs.ectester.common.ec.EC_Key; +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.data.EC_Store; +import cz.crcs.ectester.reader.CardMngr; +import cz.crcs.ectester.reader.ECTesterReader; +import cz.crcs.ectester.reader.command.Command; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CardCofactorTestSuite extends CardTestSuite { + public CardCofactorTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { + super(writer, cfg, cardManager, "cofactor", "The cofactor test suite tests whether the card correctly rejects points on the curve but not in the subgroup generated by the generator during ECDH."); + } + + @Override + protected void runTests() throws Exception { + Map pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "cofactor"); + Map> curves = new HashMap<>(); + for (EC_Key.Public key : pubkeys.values()) { + EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, key.getCurve()); + List keys = curves.getOrDefault(curve, new LinkedList<>()); + keys.add(key); + curves.putIfAbsent(curve, keys); + } + for (Map.Entry> e : curves.entrySet()) { + EC_Curve curve = e.getKey(); + List keys = e.getValue(); + + Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); + Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); + Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); + + Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); + + List 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.CORRUPTION_NONE, ECTesterApplet.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])); + + doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Cofactor test of " + curve.getId(), prepare, ecdh)); + new Command.Cleanup(this.card).send(); + } + } +} -- cgit v1.3.1 From 2a077441dc10918acf8a1f4f7c671d31b832ff4f Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 6 Mar 2018 01:21:48 +0100 Subject: Add points on non-generator subgroup for SECG curves to cofactor category. --- docs/TESTS.md | 3 +- src/cz/crcs/ectester/data/cofactor/keys.xml | 62 ++++--- src/cz/crcs/ectester/data/cofactor/secg_keys.xml | 216 +++++++++++++++++++++++ 3 files changed, 252 insertions(+), 29 deletions(-) create mode 100644 src/cz/crcs/ectester/data/cofactor/secg_keys.xml (limited to 'docs') diff --git a/docs/TESTS.md b/docs/TESTS.md index 8f8fa2e..d2eb500 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -47,6 +47,7 @@ tests all curves for which test-vectors are provided. Tests on a category of wrong curves. These curves are not really curves as they have: - non-prime field in the prime-field case - reducible polynomial as the field polynomial in the binary case + This test suite also does some additional tests with corrupting the field parameter: - Fp: - p = 0 @@ -68,7 +69,7 @@ does all wrong curve tests. ## Composite Tests using curves that don't have a prime order/nearly prime order. -These tests should generally fail, a success here implies the card **WILL** use a non-secure curve if such curve is set +These tests should generally fail, a success here implies the card will use a non-secure curve if such curve is set by the applet. Operations over such curves are susceptible to small-subgroup attacks. For example: diff --git a/src/cz/crcs/ectester/data/cofactor/keys.xml b/src/cz/crcs/ectester/data/cofactor/keys.xml index 2d827cd..f65080a 100644 --- a/src/cz/crcs/ectester/data/cofactor/keys.xml +++ b/src/cz/crcs/ectester/data/cofactor/keys.xml @@ -1,91 +1,97 @@ + + ]> + - cofactor2p128_1 + cofactor2p128/0 0x1274cf343b12c9de044a312c7e0d88b1,0x00000000000000000000000000000000 cofactor/cofactor2p128 - + order = 2 - cofactor4p128_1 + cofactor4p128/0 0x4e5a1eb60f6d2cb5c24f6ea54a675cd6,0x00000000000000000000000000000000 cofactor/cofactor4p128 - + order = 2 - cofactor8p128_1 + cofactor8p128/0 0x31eb5f732057b0ea57eed55f4259d85d,0x00000000000000000000000000000000 cofactor/cofactor8p128 - + order = 2 - cofactor16p128_1 + cofactor16p128/0 0x89578c4527e2d5e8a95905e30f0889e3,0x00000000000000000000000000000000 cofactor/cofactor16p128 - + order = 2 - cofactor32p128_1 + cofactor32p128/0 0x097191ee5ded1c36f2ec6bba78e7e6ea,0x00000000000000000000000000000000 cofactor/cofactor32p128 - + order = 2 - cofactor64p128_1 + cofactor64p128/0 0x1d360b7f2f805be59aedeaae2813ee1f,0x00000000000000000000000000000000 cofactor/cofactor64p128 - + order = 2 - cofactor128p128_1 + cofactor128p128/0 0x485b34188824c54f115f31891c18795c,0x00000000000000000000000000000000 cofactor/cofactor128p128 - + order = 2 - cofactor2t163_1 + cofactor2t163/0 0x000000000000000000000000000000000000000000,0x0132720c6aa3f2ca65d18f2de81e5e6b8ad4a3ef9d cofactor/cofactor2t163 - + order = 2 - cofactor4t163_1 + cofactor4t163/0 0x000000000000000000000000000000000000000000,0x00b93d46bc80b487e7738644e85bb6d29c2dca2600 cofactor/cofactor4t163 - + order = 2 - cofactor8t163_1 + cofactor8t163/0 0x000000000000000000000000000000000000000000,0x0569879d9674b06578f62ec2f341ddd3b648dfdf51 cofactor/cofactor8t163 - + order = 2 - cofactor16t163_1 + cofactor16t163/0 0x000000000000000000000000000000000000000000,0x04274cf55c49c32ca4c0e30b891e03b3b1c6597df0 cofactor/cofactor16t163 - + order = 2 - cofactor32t163_1 + cofactor32t163/0 0x000000000000000000000000000000000000000000,0x0409969efb468e8f07954a3b4bf7610a0d8b5d4753 cofactor/cofactor32t163 - + order = 2 - cofactor64t163_1 + cofactor64t163/0 0x000000000000000000000000000000000000000000,0x068c5445c03a59d697573b09ae0804e2891bb98208 cofactor/cofactor64t163 - + order = 2 - cofactor128t163_1 + cofactor128t163/0 0x000000000000000000000000000000000000000000,0x06be374502a948489de2e7d8d82cb6b62a493b77a0 cofactor/cofactor128t163 - + order = 2 + + &secg; diff --git a/src/cz/crcs/ectester/data/cofactor/secg_keys.xml b/src/cz/crcs/ectester/data/cofactor/secg_keys.xml new file mode 100644 index 0000000..d9d3896 --- /dev/null +++ b/src/cz/crcs/ectester/data/cofactor/secg_keys.xml @@ -0,0 +1,216 @@ + + + sect163k1/0 + 0x000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000001 + secg/sect163k1 + order = 2 + + + sect163k1/1 + 0x07759edd174e24fd20b34e6d43e51230f0f7f892ab,0x05e4bf4321769ea3f4dc92abe028069f8db0fc0dc1 + secg/sect163k1 + order = 0x800000000000000000004021145c1981b33f14bde + + + + sect163r1/0 + 0x000000000000000000000000000000000000000000,0x009917a2556e1856bc7ea9a472cd01bfb889b95835 + secg/sect163r1 + order = 2 + + + sect163r1/1 + 0x05a78dd5973d0d39a5970d49b7a13df98558981dcb,0x0340755fa31149f5bf1dd4bf1fa3ef38432babbe13 + secg/sect163r1 + order = 0x7fffffffffffffffffffe91556d1385394e204f36 + + + + sect163r2/0 + 0x000000000000000000000000000000000000000000,0x02c25b85badf8927593d21c366da89c03969f34da5 + secg/sect163r2 + order = 2 + + + sect163r2/1 + 0x00b8a6683b6d99c044e1086e4eef5d2bd80fd2df41,0x04f6dfa693e7017de96c6e002871b72b3eb6d77b83 + secg/sect163r2 + order = 0x80000000000000000000525fcefce182548469866 + + + + sect233k1/0 + 0x000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000001 + secg/sect233k1 + order = 2 + + + sect233k1/1 + 0x000000000000000000000000000000000000000000000000000000000001,0x000000000000000000000000000000000000000000000000000000000001 + secg/sect233k1 + order = 2 + + + sect233k1/2 + 0x01c90d47aff1ed1172eb861cbc5f11ade07f775b1fdd89b1665c464a97d9,0x002b41324d806a174953fb4ccf8bbeb4fd36cef6f30ccc93618dd282a8e0 + secg/sect233k1 + order = 0x100000000000000000000000000000d3ab7722b79a8ddf635abe2e757be + + + sect233k1/3 + 0x01f477bff0fda3ecd2fa1dff08045717ccf615189375e2437f539c1e1687,0x019f18a66f38eda89284e3979b2aa6ae034cc4a6c7999080815af028bafe + secg/sect233k1 + order = 0x200000000000000000000000000001a756ee456f351bbec6b57c5ceaf7c + + + + sect233r1/0 + 0x000000000000000000000000000000000000000000000000000000000000,0x0187f85627b97874e747ee31e06d71caaeea52f21253e5f946d061da9138 + secg/sect233r1 + order = 2 + + + sect233r1/1 + 0x00fe7bac18bdc41b4adbabaaa5dd95e7a170b63bb3519b5d897205fe779f,0x0109d0b6ef40d7f05129ee664be44ae57393716c0233857db6a3358926f7 + secg/sect233r1 + order = 0x2000000000000000000000000000027d2e9ce5f14d244063a4c079fc1ae + + + + sect239k1/0 + 0x000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000001 + secg/sect239k1 + order = 2 + + + sect239k1/1 + 0x000000000000000000000000000000000000000000000000000000000001,0x000000000000000000000000000000000000000000000000000000000001 + secg/sect239k1 + order = 4 + + + sect239k1/2 + 0x2e97f4bf96f4598e4dbbba188895e14b068d9c21ab8e261ffc7d43abc0f2,0x16e86c56595addfdaad811d4bc01df886838cb761332a5bd65f846d63dd3 + secg/sect239k1 + order = 0x400000000000000000000000000000b4f3fd8cf96dd23e383b5001c8f14a + + + sect239k1/3 + 0x718e787b457b7baf3b58bf38c42dd3347802801386fbbe78c4dd5ea31cc0,0x180ad3b3a1182279d21cdd1de3067572c5fe64c3641cc171515c68128cb9 + secg/sect239k1 + order = 0x80000000000000000000000000000169e7fb19f2dba47c7076a00391e294 + + + + sect283k1/0 + 0x000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000001 + secg/sect283k1 + order = 2 + + + sect283k1/1 + 0x000000000000000000000000000000000000000000000000000000000000000000000001,0x000000000000000000000000000000000000000000000000000000000000000000000000 + secg/sect283k1 + order = 4 + + + sect283k1/2 + 0x07801fcb7c8e5dd6f8c21c60dd7c13cd472dedffe20c3331d084eb4ba32f7b4b13a3510c,0x01960ead4b2a835d27a626fab5fc6e779b511c680a5e6af9b42d67228261a2add4220335 + secg/sect283k1 + order = 0x3ffffffffffffffffffffffffffffffffffd35c5da0eaee4cbbfeff288a3c0c3c2c78c2 + + + sect283k1/3 + 0x00896ce7c7065cc160ca721127910f598edc8b1e9be077d4756f31aee5705a00302d2e1d,0x0381c6394dbf16cf75f9e79c830e57e5a398ba77258e6d224692940eb925ec0b78ece889 + secg/sect283k1 + order = 0x7ffffffffffffffffffffffffffffffffffa6b8bb41d5dc9977fdfe511478187858f184 + + + + sect283r1/0 + 0x000000000000000000000000000000000000000000000000000000000000000000000000,0x072bcc9c5792b1ebe81983089fb6f835a2fd220a304424ca17c082ae17442aede9b9b3f6 + secg/sect283r1 + order = 2 + + + sect283r1/1 + 0x0743efa0a997ab11f696f61403759fa6dac093afe26160fa6d4620dc10c73ecbd07d868d,0x013abc297e8c6568601a70a323208d22730b654374643683bb913daaf0910ff492cfb1c5 + secg/sect283r1 + order = 0x7ffffffffffffffffffffffffffffffffffdf20732cc1f92715202cb60854f9df5b660e + + + + sect409k1/0 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + secg/sect409k1 + order = 2 + + + sect409k1/1 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + secg/sect409k1 + order = 4 + + + sect409k1/2 + 0x013b10b72703d774f4873f985742cce57b9377e5f89049e493eac66748870f718ae0f3ae227b6d75f7e5f810d91da79f985cefdc,0x001aea0d33e0ae234db866482308cbc579e9c7cab1fad1b62dac2a3ea16bec7ca504da1d86370fc748d1ddbc443c8a920c7b9d14 + secg/sect409k1 + order = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffcbf0765a9d440801d88aafabda7c7cf94b696b90771c03cbf9e + + + sect409k1/3 + 0x00a6cc45b0ed549286beb3f391467dcd5106fed4fb850e0ca45ac7a5291fa1f73c2ebd66b5eb2fc6c3ad93a225c20e29d76172e1,0x019c34bda5074fe8c75e1017d8b64a87766467083fb6e17a4fc57ca39c6801a31eb71e824fa225922e361db0946c4a3e7445468d + secg/sect409k1 + order = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffff97e0ecb53a881003b1155f57b4f8f9f296d2d720ee380797f3c + + + + sect409r1/0 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x009935f7e4768ee2ef22f9b4a29f53cb5d93ab2ed0ad7ce57c1b2649fde895950cf6576773326c528a48e27b872accf0bc25d5ef + secg/sect409r1 + order = 2 + + + sect409r1/1 + 0x01f8a55ff6e55b1d023eca11efc629aedba15e7683f948a84ef6e3746470b2fe9f9c694f862714ec8dbb35ae8e5b760f488ae84a,0x00c0bbc113adacdb9815bb210178b081ef4b40c949fe52345ad21eab210667cc10b5ac0e60d7bb44fee1d6c544b3cc3a18ad0a23 + secg/sect409r1 + order = 0x20000000000000000000000000000000000000000000000000003c555ad4c25e6660f7cbf48f8793c0a5f0702c99a6fb34422e6 + + + + sect571k1/0 + 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 + secg/sect571k1 + order = 2 + + + sect571k1/1 + 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + secg/sect571k1 + order = 4 + + + sect571k1/2 + 0x0311efd68e031548397fd197f3c9ea9ef2048b3835bbb52c06cc89fa29a609be1a4215805132ed6c30ed743e6221f34c5d43acd3777c88a42578a7b02d2a9af488c138b206832707,0x01692831faeb78797365873933fd9c5f5223d2bceba37aa6a4f6d128973e3263b124300568f039541e51c6214409523179aaecdf76e789921d84e12991113eacd03727d4c9754920 + secg/sect571k1 + order = 0x400000000000000000000000000000000000000000000000000000000000000000000002630a1c3e334c7c9672351b722fe82716c61b097cbac72703d23bd68b9fcef1ec6f82002 + + + sect571k1/3 + 0x0519146e2a901338dce58310d786d30fd6806c620f6a7a9ba4389534dcdf16c6becdacb853fad56e4b048465b4037450468fb9bc6259448ce84a92fd8bfe9c3663dad3da48089517,0x05671e892895ca17683107f21da7741a3fdf47e546dfc6b6d2ed83c970ac88c33b7b522b0a1fe9a7dda46a7075d4881e88b9fc7f3a2002883f6c7d651f9c94252340b59b8abc0aeb + secg/sect571k1 + order = 0x800000000000000000000000000000000000000000000000000000000000000000000004c614387c6698f92ce46a36e45fd04e2d8c3612f9758e4e07a477ad173f9de3d8df04004 + + + + sect571r1/0 + 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0732d556640c20b5dd739a058dffd58268d41c59135429eb041d7aa1255902e6362c4800a874ab0b60536b58460cd20c06f0340e3594a7f771bedfc10ce39b64699b08443b761c43 + secg/sect571r1 + order = 2 + + + sect571r1/1 + 0x01e4b7514be19101ec1d9f032bdba65dd1d73465bc1425e3847f44b7b2c78669358ab7bb34dec5202db32c0e65f8f4e0c5c0db8ae19537307ba6391dfa7831375b1b3957d403477a,0x00f04eb4a9ce0f18f879143faea24107682602d9319105a62c2758da491014ae34280a32830a1e239d0e89b3a3ff60acb640afc01aa56dcb8344423f0ad9f071af3d95d7675578fc + secg/sect571r1 + order = 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffccc39c31feab30e6100b3630d0470a3d8fbb39422c3bd27aa2e9acdd0705d3765fd09c8e + \ No newline at end of file -- cgit v1.3.1 From ea6cc551158e9e124e2ad82cb29948ea547acf2b Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 28 Apr 2018 19:47:47 +0200 Subject: Add documentation about degenerate test suite. --- README.md | 4 +++- docs/CURVES.md | 6 ++++++ docs/TESTS.md | 15 ++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 71c7042..5ff720d 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ Following operations are tested: - Setting of custom curve and KeyPair generation - Generation of shared secret via ECDH - Signature via ECDSA -- Behavior of card when invalid curves/points are provided (should fail) See `java -jar ECTesterReader.jar -h` for more. @@ -39,6 +38,9 @@ See `java -jar ECTesterReader.jar -h` for more. -t,--test Test ECC support. [test_suite]: - default: - invalid: + - twist: + - degenerate: + - cofactor: - wrong: - composite: - test-vectors: diff --git a/docs/CURVES.md b/docs/CURVES.md index a815c5c..a0454a3 100644 --- a/docs/CURVES.md +++ b/docs/CURVES.md @@ -62,6 +62,12 @@ These points can be used to attack some implementations. Generated using [ecgen](https://github.com/J08nY/ecgen). +### degenerate +Contains pre-generated points on the line `Y: x = 0`. These points are constructed from elements of prime +order in the multiplicative group F_p given a curve over it. + +Generate manually using [PARI/GP](http://pari.math.u-bordeaux.fr/). + ### cofactor Contains curves that are composite order, with points not on the subgroup generated by the generator. diff --git a/docs/TESTS.md b/docs/TESTS.md index d2eb500..bd70206 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -6,9 +6,10 @@ - `composite` - `invalid` - `twist` + - `degenerate` - `cofactor` -**NOTE: The `wrong`, `composite`, `invalid`,`twist` and `cofactor` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for +**NOTE: The `wrong`, `composite`, `invalid`,`twist`, `cofactor` and `degenerate` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for confirmation before running, be cautious.** ## Default @@ -103,6 +104,18 @@ For example: java -jar ECTester.jar -t twist ``` +## Degenerate +Tests using known named curves froms several categories(SECG/NIST) against pre-generated points on the degenerate line +`Y: x = 0`. ECDH should fail, a success here might mean the card does not check that the point lies on the correct curve +and uses a curve model vulnerable to such degenerate points. + +See [Degenerate Curve Attachs - Extending Invalid Curve Attacks to Edwards Curves and Other Models](https://eprint.iacr.org/2015/1233.pdf) for more information. + +For example: +```bash +java -jar ECTester.jar -t degenerate +``` + ## Cofactor Tests whether the card correctly rejects points that lie on the curve but not on the subgroup generated by the specified generator during ECDH. -- cgit v1.3.1 From 92c28a15e018e55b8f195993414f769ecf96a663 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 28 Apr 2018 21:19:16 +0200 Subject: Add degenerate curves for brainpool 512 bit prime curve. --- docs/TESTS.md | 2 +- src/cz/crcs/ectester/data/degenerate/brainpool.xml | 51 ++++++++++++++++++++-- 2 files changed, 49 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/TESTS.md b/docs/TESTS.md index bd70206..5f4dd9c 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -109,7 +109,7 @@ Tests using known named curves froms several categories(SECG/NIST) against pre-g `Y: x = 0`. ECDH should fail, a success here might mean the card does not check that the point lies on the correct curve and uses a curve model vulnerable to such degenerate points. -See [Degenerate Curve Attachs - Extending Invalid Curve Attacks to Edwards Curves and Other Models](https://eprint.iacr.org/2015/1233.pdf) for more information. +See [Degenerate Curve Attacks - Extending Invalid Curve Attacks to Edwards Curves and Other Models](https://eprint.iacr.org/2015/1233.pdf) for more information. For example: ```bash diff --git a/src/cz/crcs/ectester/data/degenerate/brainpool.xml b/src/cz/crcs/ectester/data/degenerate/brainpool.xml index 9dc860a..3dd2f54 100644 --- a/src/cz/crcs/ectester/data/degenerate/brainpool.xml +++ b/src/cz/crcs/ectester/data/degenerate/brainpool.xml @@ -310,8 +310,53 @@ generator of Fp^* - + + brainpoolP512r1/0 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f2 + brainpool/brainpoolP512r1 + degenerate order = 2 + + + brainpoolP512r1/1 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x177c47f1f2bd3306efe5a93ed046a559abbb32424d5887e6c3f49c23c907c5a3b68aee1d7ae4247ba3491698c3c7c4dd9e105383f58984e45b4104cce042417b + brainpool/brainpoolP512r1 + degenerate order = 7 + + + brainpoolP512r1/2 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x9b9e9905d13f35cc5b6578523e0380be922803fa98bcde94c920aca572a8fb4a432520b51b0f9eb3d854aa14aa5ef9fcc4ac08bf06eaec4b98ffdf90244f67d7 + brainpool/brainpoolP512r1 + degenerate order = 61 + + + brainpoolP512r1/3 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x77b03a217034dd2adcbcbfbdfe879b4ce1f0ecdd6025d1c3da80bef3e905a34bfdcb88362d553219b025cb8123698296c437411ecba452db94d829729def073e + brainpool/brainpoolP512r1 + degenerate order = 329430728783919403 + + + brainpoolP512r1/4 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x890e0b1d03bd78442f0144b752cce879cec7a069497a83a6dac714a37221fa282ef147385b796653c2b98c87c003a7285ee98f69ed3df135c6a59adf8f17be5a + brainpool/brainpoolP512r1 + degenerate order = 18335424362847464339 + + + brainpoolP512r1/5 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x25c0f1328c75876e338e66fb112cd47e8936c41b57dbf2c97de9c6bf300fb035bbcb20fb44046e6172c00939075da436b9c7d84941a9b98219fced6d9e17da64 + brainpool/brainpoolP512r1 + degenerate order = 120179186709126902983513742993 + + + brainpoolP512r1/6 + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x1d93c72f487fc4ad34cb0c522dda3a7067b1b5c11175fc90ebbd086f639cad2d30d345e5596a93136e48aad4226cdb1a320e4b0aa68da2ca62cd5fe51c601f8e + brainpool/brainpoolP512r1 + degenerate order = 14435454750020088047685444818571282397270727096595623715684950293729763357371155607979 + + + brainpoolP512r1/gen + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 + brainpool/brainpoolP512r1 + generator of Fp^* + -- cgit v1.3.1 From 78e5e3d53c20bac2cb33e7ace8565173651c6155 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 2 May 2018 20:33:42 +0200 Subject: Add compression suite to docs and comments. --- README.md | 60 +++++++++++++--------- docs/TESTS.md | 23 ++++++--- src/cz/crcs/ectester/reader/ECTesterReader.java | 2 +- .../ectester/reader/test/CardCompressionSuite.java | 3 +- 4 files changed, 54 insertions(+), 34 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 5ff720d..7b280bb 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ See `java -jar ECTesterReader.jar -h` for more. -t,--test Test ECC support. [test_suite]: - default: - invalid: + - compression: - twist: - degenerate: - cofactor: @@ -158,32 +159,41 @@ This shows that JCardsim simulates 112b Fp support with default curve present an > java -jar ECTesterReader.jar -t -s ═══ Running test suite: default ═══ - ═══ The default test suite run basic support of ECDH and ECDSA. + ═══ The default test suite tests basic support of ECDH and ECDSA. + ═══ Date: 2018.05.02 20:29:38 + ═══ ECTester version: v0.2.0 ═══ Card ATR: 3bfa1800008131fe454a434f5033315632333298 - NOK ┳ Tests of 112b ALG_EC_FP support. Some. ┃ FAILURE ┃ Some sub-tests did not have the expected result. - ┣ OK ━ Allocated both keypairs 112b ALG_EC_FP ┃ SUCCESS ┃ 50 ms ┃ OK (0x9000) OK (0x9000) - ┣ OK ━ Generated both keypairs ┃ SUCCESS ┃ 37 ms ┃ OK (0x9000) OK (0x9000) - ┣ OK ━ Set custom curve parameters on both keypairs ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000) OK (0x9000) - ┣ OK ━ Generated both keypairs ┃ SUCCESS ┃ 16 ms ┃ OK (0x9000) OK (0x9000) - ┣ OK ┳ Test of the ALG_EC_SVDP_DH KeyAgreement. ┃ SUCCESS ┃ All sub-tests had the expected result. - ┃ ┣ OK ━ Allocated KeyAgreement(ALG_EC_SVDP_DH) object ┃ SUCCESS ┃ 2 ms ┃ OK (0x9000) - ┃ ┣ OK ━ ALG_EC_SVDP_DH of local pubkey and remote privkey(unchanged point) ┃ SUCCESS ┃ 7 ms ┃ OK (0x9000) - ┃ ┗ OK ━ ALG_EC_SVDP_DH of local pubkey and remote privkey(COMPRESSED point) ┃ SUCCESS ┃ 14 ms ┃ OK (0x9000) - ┣ OK ┳ Test of the ALG_EC_SVDP_DHC KeyAgreement. ┃ SUCCESS ┃ All sub-tests had the expected result. - ┃ ┣ OK ━ Allocated KeyAgreement(ALG_EC_SVDP_DHC) object ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000) - ┃ ┣ OK ━ ALG_EC_SVDP_DHC of local pubkey and remote privkey(unchanged point) ┃ SUCCESS ┃ 3 ms ┃ OK (0x9000) - ┃ ┗ OK ━ ALG_EC_SVDP_DHC of local pubkey and remote privkey(COMPRESSED point) ┃ SUCCESS ┃ 5 ms ┃ OK (0x9000) - ┣ NOK ━ Allocated KeyAgreement(ALG_EC_SVDP_DH_PLAIN) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) - ┣ NOK ━ Allocated KeyAgreement(ALG_EC_SVDP_DHC_PLAIN) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) - ┣ NOK ━ Allocated KeyAgreement(ALG_EC_PACE_GM) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) - ┣ NOK ━ Allocated KeyAgreement(ALG_EC_SVDP_DH_PLAIN_XY) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) - ┣ OK ┳ Test of the ALG_ECDSA_SHA signature. ┃ SUCCESS ┃ All sub-tests had the expected result. - ┃ ┣ OK ━ Allocated Signature(ALG_ECDSA_SHA) object ┃ SUCCESS ┃ 7 ms ┃ OK (0x9000) - ┃ ┗ OK ━ ALG_ECDSA_SHA with local keypair(random data) ┃ SUCCESS ┃ 43 ms ┃ OK (0x9000) - ┣ NOK ━ Allocated Signature(ALG_ECDSA_SHA_224) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) - ┣ NOK ━ Allocated Signature(ALG_ECDSA_SHA_256) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) - ┣ NOK ━ Allocated Signature(ALG_ECDSA_SHA_384) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) - ┗ NOK ━ Allocated Signature(ALG_ECDSA_SHA_512) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) + OK ┳ Tests of 112b ALG_EC_FP support. ┃ SUCCESS ┃ All sub-tests matched the expected mask. + ┣ OK ━ Allocate both keypairs 112b ALG_EC_FP ┃ SUCCESS ┃ 22 ms ┃ OK (0x9000) OK (0x9000) + ┣ OK ━ Generate both keypairs ┃ SUCCESS ┃ 23 ms ┃ OK (0x9000) OK (0x9000) + ┣ OK ━ Allocate both keypairs 112b ALG_EC_FP ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000) OK (0x9000) + ┣ OK ━ Set custom curve parameters on both keypairs ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000) OK (0x9000) + ┣ OK ━ Generate both keypairs ┃ SUCCESS ┃ 8 ms ┃ OK (0x9000) OK (0x9000) + ┣ OK ┳ KeyAgreement tests. ┃ SUCCESS ┃ Some sub-tests did have the expected result. + ┃ ┣ OK ┳ Test of the ALG_EC_SVDP_DH KeyAgreement. ┃ SUCCESS ┃ Some ECDH is supported. + ┃ ┃ ┣ OK ━ Allocate KeyAgreement(ALG_EC_SVDP_DH) object ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000) + ┃ ┃ ┣ OK ━ ALG_EC_SVDP_DH of local pubkey and remote privkey(unchanged point) ┃ SUCCESS ┃ 2 ms ┃ OK (0x9000) + ┃ ┃ ┣ OK ━ ALG_EC_SVDP_DH of local pubkey and remote privkey(COMPRESSED point) ┃ SUCCESS ┃ 2 ms ┃ OK (0x9000) + ┃ ┃ ┗ OK ━ Mean = 1722885 ns, Median = 1718807 ns, Mode = 1614047 ns ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000) + ┃ ┣ OK ┳ Test of the ALG_EC_SVDP_DHC KeyAgreement. ┃ SUCCESS ┃ Some ECDH is supported. + ┃ ┃ ┣ OK ━ Allocate KeyAgreement(ALG_EC_SVDP_DHC) object ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000) + ┃ ┃ ┣ OK ━ ALG_EC_SVDP_DHC of local pubkey and remote privkey(unchanged point) ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000) + ┃ ┃ ┣ OK ━ ALG_EC_SVDP_DHC of local pubkey and remote privkey(COMPRESSED point) ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000) + ┃ ┃ ┗ OK ━ Mean = 1563980 ns, Median = 1549170 ns, Mode = 1514747 ns ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000) + ┃ ┣ NOK ━ Allocate KeyAgreement(ALG_EC_SVDP_DH_PLAIN) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) + ┃ ┣ NOK ━ Allocate KeyAgreement(ALG_EC_SVDP_DHC_PLAIN) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) + ┃ ┣ NOK ━ Allocate KeyAgreement(ALG_EC_PACE_GM) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) + ┃ ┗ NOK ━ Allocate KeyAgreement(ALG_EC_SVDP_DH_PLAIN_XY) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) + ┗ OK ┳ Signature tests. ┃ SUCCESS ┃ Some sub-tests did have the expected result. + ┣ OK ┳ Test of the ALG_ECDSA_SHA signature. ┃ SUCCESS ┃ All sub-tests had the expected result. + ┃ ┣ OK ━ Allocate Signature(ALG_ECDSA_SHA) object ┃ SUCCESS ┃ 3 ms ┃ OK (0x9000) + ┃ ┣ OK ━ ALG_ECDSA_SHA with local keypair(random data) ┃ SUCCESS ┃ 14 ms ┃ OK (0x9000) + ┃ ┣ OK ━ Sign (Mean = 1890914 ns, Median = 1500125 ns, Mode = 1422588 ns) ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000) + ┃ ┗ OK ━ Verify (Mean = 1873952 ns, Median = 1870348 ns, Mode = 1843902 ns) ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000) + ┣ NOK ━ Allocate Signature(ALG_ECDSA_SHA_224) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) + ┣ NOK ━ Allocate Signature(ALG_ECDSA_SHA_256) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) + ┣ NOK ━ Allocate Signature(ALG_ECDSA_SHA_384) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) + ┗ NOK ━ Allocate Signature(ALG_ECDSA_SHA_512) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003) #### Legend - Some general information about the test suite and card is output first, test data follows after. diff --git a/docs/TESTS.md b/docs/TESTS.md index 5f4dd9c..d2c3ab5 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -2,14 +2,15 @@ - `default` - `test-vectors` - - `wrong` - - `composite` - - `invalid` - - `twist` - - `degenerate` - - `cofactor` + - `compression` + - `wrong`* + - `composite`* + - `invalid`* + - `twist`* + - `degenerate`* + - `cofactor`* -**NOTE: The `wrong`, `composite`, `invalid`,`twist`, `cofactor` and `degenerate` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for +**\*NOTE: The `wrong`, `composite`, `invalid`,`twist`, `cofactor` and `degenerate` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for confirmation before running, be cautious.** ## Default @@ -43,6 +44,14 @@ java -jar ECTester.jar -t test-vectors ``` tests all curves for which test-vectors are provided. +## Compression +Tests support for compression of public points in ECDH as specified in ANSI X9.62. Tests ECDH with points in compressed +and hybrid form. Also tests card response to a hybrid point with wrong `y` coordinate and to the point at infinity(as public key in ECDH). + +For example: +```bash +java -jar ECTester.jar -t compression +``` ## Wrong Tests on a category of wrong curves. These curves are not really curves as they have: diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java index 6098cd4..68bb3d8 100644 --- a/src/cz/crcs/ectester/reader/ECTesterReader.java +++ b/src/cz/crcs/ectester/reader/ECTesterReader.java @@ -247,7 +247,7 @@ public class ECTesterReader { actions.addOption(Option.builder("ln").longOpt("list-named").desc("Print the list of supported named curves and keys.").hasArg().argName("what").optionalArg(true).build()); actions.addOption(Option.builder("e").longOpt("export").desc("Export the defaut curve parameters of the card(if any).").build()); actions.addOption(Option.builder("g").longOpt("generate").desc("Generate [amount] of EC keys.").hasArg().argName("amount").optionalArg(true).build()); - actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. [test_suite]:\n- default:\n- invalid:\n- twist:\n- degenerate:\n- cofactor:\n- wrong:\n- composite:\n- test-vectors:").hasArg().argName("test_suite").optionalArg(true).build()); + actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. [test_suite]:\n- default:\n- compression:\n- invalid:\n- twist:\n- degenerate:\n- cofactor:\n- wrong:\n- composite:\n- test-vectors:").hasArg().argName("test_suite").optionalArg(true).build()); actions.addOption(Option.builder("dh").longOpt("ecdh").desc("Do EC KeyAgreement (ECDH...), [count] times.").hasArg().argName("count").optionalArg(true).build()); actions.addOption(Option.builder("dsa").longOpt("ecdsa").desc("Sign data with ECDSA, [count] times.").hasArg().argName("count").optionalArg(true).build()); diff --git a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java index 7300653..e58c38d 100644 --- a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java @@ -24,7 +24,8 @@ import java.util.List; */ public class CardCompressionSuite extends CardTestSuite { public CardCompressionSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "compression", ""); + super(writer, cfg, cardManager, "compression", "The compression test suite tests cards support for compressed points in ECDH (as per ANSI X9.62).\n" + + "It also tests for handling of bogus input by using the point at infinity and a hybrid point with the y coordinate corrupted."); } @Override -- cgit v1.3.1 From 9e2f1532b0c939c858f40397c2fbda7d3293e3fc Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 23 May 2018 18:47:10 +0200 Subject: Add the AddSubChain wycheproof vectors. --- docs/LIBS.md | 3 +- src/cz/crcs/ectester/common/ec/EC_Curve.java | 2 +- src/cz/crcs/ectester/common/ec/EC_KAResult.java | 2 +- src/cz/crcs/ectester/common/ec/EC_Key.java | 4 +- src/cz/crcs/ectester/common/ec/EC_Keypair.java | 2 +- src/cz/crcs/ectester/data/categories.xml | 5 + src/cz/crcs/ectester/data/wycheproof/keys.xml | 851 ++++++++++++++++++++++++ 7 files changed, 863 insertions(+), 6 deletions(-) create mode 100644 src/cz/crcs/ectester/data/wycheproof/keys.xml (limited to 'docs') diff --git a/docs/LIBS.md b/docs/LIBS.md index 1f1f92c..a1395bc 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -17,12 +17,13 @@ Libraries with at least some ECC support: - Java - [Sun EC](https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunEC) - Java + C - - [Botan](https://botan.randombit.net/), since 2.4.0 (unreleased) + - [Botan](https://botan.randombit.net/) - C++ - Uses blinded(randomized) Montgomery ladder. - https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2 - https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc - https://eprint.iacr.org/2015/657 + - ECTester supports v2.4.0 and up. - [libtomcrypt](http://www.libtom.net/LibTomCrypt/) - C - Uses Jacobian coordinates. diff --git a/src/cz/crcs/ectester/common/ec/EC_Curve.java b/src/cz/crcs/ectester/common/ec/EC_Curve.java index 8338a93..6c0d060 100644 --- a/src/cz/crcs/ectester/common/ec/EC_Curve.java +++ b/src/cz/crcs/ectester/common/ec/EC_Curve.java @@ -51,7 +51,7 @@ public class EC_Curve extends EC_Params { @Override public String toString() { - return "<" + getId() + "> " + (field == KeyPair.ALG_EC_FP ? "Prime" : "Binary") + " field Elliptic curve (" + String.valueOf(bits) + "b)" + (desc == null ? "" : ": " + desc); + return "<" + getId() + "> " + (field == KeyPair.ALG_EC_FP ? "Prime" : "Binary") + " field Elliptic curve (" + String.valueOf(bits) + "b)" + (desc == null ? "" : ": " + desc) + System.lineSeparator() + super.toString(); } public EllipticCurve toCurve() { diff --git a/src/cz/crcs/ectester/common/ec/EC_KAResult.java b/src/cz/crcs/ectester/common/ec/EC_KAResult.java index 8a5fcb4..4e97950 100644 --- a/src/cz/crcs/ectester/common/ec/EC_KAResult.java +++ b/src/cz/crcs/ectester/common/ec/EC_KAResult.java @@ -59,7 +59,7 @@ public class EC_KAResult extends EC_Data { @Override public String toString() { - return "<" + getId() + "> " + ka + " result over " + curve + ", " + oneKey + " + " + otherKey + (desc == null ? "" : ": " + desc); + return "<" + getId() + "> " + ka + " result over " + curve + ", " + oneKey + " + " + otherKey + (desc == null ? "" : ": " + desc) + System.lineSeparator() + super.toString(); } } diff --git a/src/cz/crcs/ectester/common/ec/EC_Key.java b/src/cz/crcs/ectester/common/ec/EC_Key.java index a34b0e7..754775d 100644 --- a/src/cz/crcs/ectester/common/ec/EC_Key.java +++ b/src/cz/crcs/ectester/common/ec/EC_Key.java @@ -54,7 +54,7 @@ public class EC_Key extends EC_Params { @Override public String toString() { - return "<" + getId() + "> EC Public key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc()); + return "<" + getId() + "> EC Public key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc()) + System.lineSeparator() + super.toString(); } } @@ -77,7 +77,7 @@ public class EC_Key extends EC_Params { @Override public String toString() { - return "<" + getId() + "> EC Private key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc()); + return "<" + getId() + "> EC Private key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc()) + System.lineSeparator() + super.toString(); } } } diff --git a/src/cz/crcs/ectester/common/ec/EC_Keypair.java b/src/cz/crcs/ectester/common/ec/EC_Keypair.java index 53632cd..24ddba7 100644 --- a/src/cz/crcs/ectester/common/ec/EC_Keypair.java +++ b/src/cz/crcs/ectester/common/ec/EC_Keypair.java @@ -36,6 +36,6 @@ public class EC_Keypair extends EC_Params { @Override public String toString() { - return "<" + getId() + "> EC Keypair, over " + curve + (desc == null ? "" : ": " + desc); + return "<" + getId() + "> EC Keypair, over " + curve + (desc == null ? "" : ": " + desc) + System.lineSeparator() + super.toString(); } } diff --git a/src/cz/crcs/ectester/data/categories.xml b/src/cz/crcs/ectester/data/categories.xml index 0e1b142..74b73a9 100644 --- a/src/cz/crcs/ectester/data/categories.xml +++ b/src/cz/crcs/ectester/data/categories.xml @@ -74,4 +74,9 @@ test Test vectors + + wycheproof + wycheproof + Test cases from google Wycheproof project: https://github.com/google/wycheproof + \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/wycheproof/keys.xml b/src/cz/crcs/ectester/data/wycheproof/keys.xml new file mode 100644 index 0000000..d8ae0c4 --- /dev/null +++ b/src/cz/crcs/ectester/data/wycheproof/keys.xml @@ -0,0 +1,851 @@ + + + + wycheproof/addsub/secp224r1/1s + 0x0ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c29b7 + secg/secp224r1 + tcId = 34 + + + wycheproof/addsub/secp224r1/1w + 0x478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac230,0x2e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504 + + secg/secp224r1 + tcId = 34 + + + wycheproof/addsub/secp224r1/2s + 0x0ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a37 + secg/secp224r1 + tcId = 35 + + + wycheproof/addsub/secp224r1/2w + 0x478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac230,0x2e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504 + + secg/secp224r1 + tcId = 35 + + + wycheproof/addsub/secp224r1/3s + 0x0ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3b + secg/secp224r1 + tcId = 37 + + + wycheproof/addsub/secp224r1/3w + 0x478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac230,0x2e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504 + + secg/secp224r1 + tcId = 37 + + + wycheproof/addsub/secp256r1/1s + 0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324f3 + secg/secp256r1 + tcId = 106 + + + wycheproof/addsub/secp256r1/1w + 0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b + + secg/secp256r1 + tcId = 106 + + + wycheproof/addsub/secp256r1/2s + 0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632533 + secg/secp256r1 + tcId = 107 + + + wycheproof/addsub/secp256r1/2w + 0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b + + secg/secp256r1 + tcId = 107 + + + wycheproof/addsub/secp256r1/3s + 0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632543 + secg/secp256r1 + tcId = 108 + + + wycheproof/addsub/secp256r1/3w + 0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b + + secg/secp256r1 + tcId = 108 + + + wycheproof/addsub/secp256r1/4s + 0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254b + secg/secp256r1 + tcId = 109 + + + wycheproof/addsub/secp256r1/4w + 0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b + + secg/secp256r1 + tcId = 109 + + + wycheproof/addsub/secp256r1/5s + 0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f + secg/secp256r1 + tcId = 111 + + + wycheproof/addsub/secp256r1/5w + 0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b + + secg/secp256r1 + tcId = 111 + + + wycheproof/addsub/secp384r1/1s + 0x0ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52959 + secg/secp384r1 + tcId = 192 + + + wycheproof/addsub/secp384r1/1w + 0xe9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c0,0x20156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e + + secg/secp384r1 + tcId = 192 + + + wycheproof/addsub/secp384r1/2s + 0x0ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52969 + secg/secp384r1 + tcId = 193 + + + wycheproof/addsub/secp384r1/2w + 0xe9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c0,0x20156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e + + secg/secp384r1 + tcId = 193 + + + wycheproof/addsub/secp384r1/3s + 0x0ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52971 + secg/secp384r1 + tcId = 195 + + + wycheproof/addsub/secp384r1/3w + 0xe9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c0,0x20156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e + + secg/secp384r1 + tcId = 195 + + + wycheproof/addsub/secp521r1/1s + 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e9138631b + secg/secp521r1 + tcId = 273 + + + wycheproof/addsub/secp521r1/1w + 0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 + + secg/secp521r1 + tcId = 273 + + + wycheproof/addsub/secp521r1/2s + 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e9138639b + secg/secp521r1 + tcId = 274 + + + wycheproof/addsub/secp521r1/2w + 0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 + + secg/secp521r1 + tcId = 274 + + + wycheproof/addsub/secp521r1/3s + 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e913863db + secg/secp521r1 + tcId = 275 + + + wycheproof/addsub/secp521r1/3w + 0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 + + secg/secp521r1 + tcId = 275 + + + wycheproof/addsub/secp521r1/4s + 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e913863fb + secg/secp521r1 + tcId = 276 + + + wycheproof/addsub/secp521r1/4w + 0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 + + secg/secp521r1 + tcId = 276 + + + wycheproof/addsub/secp521r1/5s + 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386403 + secg/secp521r1 + tcId = 277 + + + wycheproof/addsub/secp521r1/5w + 0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 + + secg/secp521r1 + tcId = 277 + + + wycheproof/addsub/secp521r1/6s + 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386407 + secg/secp521r1 + tcId = 279 + + + wycheproof/addsub/secp521r1/6w + 0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 + + secg/secp521r1 + tcId = 279 + + + wycheproof/addsub/secp256k1/1s + 0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c3 + secg/secp256k1 + tcId = 362 + + + wycheproof/addsub/secp256k1/1w + 0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b + + secg/secp256k1 + tcId = 362 + + + wycheproof/addsub/secp256k1/2s + 0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364103 + secg/secp256k1 + tcId = 363 + + + wycheproof/addsub/secp256k1/2w + 0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b + + secg/secp256k1 + tcId = 363 + + + wycheproof/addsub/secp256k1/3s + 0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364123 + secg/secp256k1 + tcId = 364 + + + wycheproof/addsub/secp256k1/3w + 0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b + + secg/secp256k1 + tcId = 364 + + + wycheproof/addsub/secp256k1/4s + 0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364133 + secg/secp256k1 + tcId = 365 + + + wycheproof/addsub/secp256k1/4w + 0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b + + secg/secp256k1 + tcId = 365 + + + wycheproof/addsub/secp256k1/5s + 0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413b + secg/secp256k1 + tcId = 366 + + + wycheproof/addsub/secp256k1/5w + 0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b + + secg/secp256k1 + tcId = 366 + + + wycheproof/addsub/secp256k1/6s + 0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f + secg/secp256k1 + tcId = 368 + + + wycheproof/addsub/secp256k1/6w + 0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b + + secg/secp256k1 + tcId = 368 + + + wycheproof/addsub/brainpoolP224r1/1s + 0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a792dd + brainpool/brainpoolP224r1 + tcId = 441 + + + wycheproof/addsub/brainpoolP224r1/1w + 0xaaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d126,0x8c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66 + + brainpool/brainpoolP224r1 + tcId = 441 + + + wycheproof/addsub/brainpoolP224r1/2s + 0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7935d + brainpool/brainpoolP224r1 + tcId = 442 + + + wycheproof/addsub/brainpoolP224r1/2w + 0xaaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d126,0x8c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66 + + brainpool/brainpoolP224r1 + tcId = 442 + + + wycheproof/addsub/brainpoolP224r1/3s + 0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939d + brainpool/brainpoolP224r1 + tcId = 444 + + + wycheproof/addsub/brainpoolP224r1/3w + 0xaaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d126,0x8c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66 + + brainpool/brainpoolP224r1 + tcId = 444 + + + wycheproof/addsub/brainpoolP256r1/1s + 0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974855f5 + brainpool/brainpoolP256r1 + tcId = 524 + + + wycheproof/addsub/brainpoolP256r1/1w + 0xa4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b3,0x77d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b + + brainpool/brainpoolP256r1 + tcId = 524 + + + wycheproof/addsub/brainpoolP256r1/2s + 0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e8297485675 + brainpool/brainpoolP256r1 + tcId = 525 + + + wycheproof/addsub/brainpoolP256r1/2w + 0xa4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b3,0x77d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b + + brainpool/brainpoolP256r1 + tcId = 525 + + + wycheproof/addsub/brainpoolP256r1/3s + 0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e8297485695 + brainpool/brainpoolP256r1 + tcId = 526 + + + wycheproof/addsub/brainpoolP256r1/3w + 0xa4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b3,0x77d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b + + brainpool/brainpoolP256r1 + tcId = 526 + + + wycheproof/addsub/brainpoolP256r1/4s + 0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a5 + brainpool/brainpoolP256r1 + tcId = 528 + + + wycheproof/addsub/brainpoolP256r1/4w + 0xa4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b3,0x77d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b + + brainpool/brainpoolP256r1 + tcId = 528 + + + wycheproof/addsub/brainpoolP320r1/1s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59233 + brainpool/brainpoolP320r1 + tcId = 604 + + + wycheproof/addsub/brainpoolP320r1/1w + 0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d + + brainpool/brainpoolP320r1 + tcId = 604 + + + wycheproof/addsub/brainpoolP320r1/2s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c592b3 + brainpool/brainpoolP320r1 + tcId = 605 + + + wycheproof/addsub/brainpoolP320r1/2w + 0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d + + brainpool/brainpoolP320r1 + tcId = 605 + + + wycheproof/addsub/brainpoolP320r1/3s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c592f3 + brainpool/brainpoolP320r1 + tcId = 606 + + + wycheproof/addsub/brainpoolP320r1/3w + 0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d + + brainpool/brainpoolP320r1 + tcId = 606 + + + wycheproof/addsub/brainpoolP320r1/4s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59303 + brainpool/brainpoolP320r1 + tcId = 607 + + + wycheproof/addsub/brainpoolP320r1/4w + 0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d + + brainpool/brainpoolP320r1 + tcId = 607 + + + wycheproof/addsub/brainpoolP320r1/5s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c5930b + brainpool/brainpoolP320r1 + tcId = 608 + + + wycheproof/addsub/brainpoolP320r1/5w + 0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d + + brainpool/brainpoolP320r1 + tcId = 608 + + + wycheproof/addsub/brainpoolP320r1/6s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c5930f + brainpool/brainpoolP320r1 + tcId = 610 + + + wycheproof/addsub/brainpoolP320r1/6w + 0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d + + brainpool/brainpoolP320r1 + tcId = 610 + + + wycheproof/addsub/brainpoolP384r1/1s + 0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904652f + brainpool/brainpoolP384r1 + tcId = 684 + + + wycheproof/addsub/brainpoolP384r1/1w + 0x09d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf,0x03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf + + brainpool/brainpoolP384r1 + tcId = 684 + + + wycheproof/addsub/brainpoolP384r1/2s + 0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904654f + brainpool/brainpoolP384r1 + tcId = 685 + + + wycheproof/addsub/brainpoolP384r1/2w + 0x09d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf,0x03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf + + brainpool/brainpoolP384r1 + tcId = 685 + + + wycheproof/addsub/brainpoolP384r1/3s + 0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904655f + brainpool/brainpoolP384r1 + tcId = 686 + + + wycheproof/addsub/brainpoolP384r1/3w + 0x09d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf,0x03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf + + brainpool/brainpoolP384r1 + tcId = 686 + + + wycheproof/addsub/brainpoolP384r1/4s + 0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046563 + brainpool/brainpoolP384r1 + tcId = 688 + + + wycheproof/addsub/brainpoolP384r1/4w + 0x09d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf,0x03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf + + brainpool/brainpoolP384r1 + tcId = 688 + + + wycheproof/addsub/brainpoolP512r1/1s + 0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca9003b + brainpool/brainpoolP512r1 + tcId = 774 + + + wycheproof/addsub/brainpoolP512r1/1w + 0x2ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc,0x99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd + + brainpool/brainpoolP512r1 + tcId = 774 + + + wycheproof/addsub/brainpoolP512r1/2s + 0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca9005b + brainpool/brainpoolP512r1 + tcId = 775 + + + wycheproof/addsub/brainpoolP512r1/2w + 0x2ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc,0x99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd + + brainpool/brainpoolP512r1 + tcId = 775 + + + wycheproof/addsub/brainpoolP512r1/3s + 0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90063 + brainpool/brainpoolP512r1 + tcId = 776 + + + wycheproof/addsub/brainpoolP512r1/3w + 0x2ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc,0x99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd + + brainpool/brainpoolP512r1 + tcId = 776 + + + wycheproof/addsub/brainpoolP512r1/4s + 0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90067 + brainpool/brainpoolP512r1 + tcId = 778 + + + wycheproof/addsub/brainpoolP512r1/4w + 0x2ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc,0x99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd + + brainpool/brainpoolP512r1 + tcId = 778 + + + wycheproof/addsub/brainpoolP224t1/1s + 0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a792dd + brainpool/brainpoolP224t1 + tcId = 854 + + + wycheproof/addsub/brainpoolP224t1/1w + 0x1b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c2,0x6709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1 + + brainpool/brainpoolP224t1 + tcId = 854 + + + wycheproof/addsub/brainpoolP224t1/2s + 0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7935d + brainpool/brainpoolP224t1 + tcId = 855 + + + wycheproof/addsub/brainpoolP224t1/2w + 0x1b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c2,0x6709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1 + + brainpool/brainpoolP224t1 + tcId = 855 + + + wycheproof/addsub/brainpoolP224t1/3s + 0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939d + brainpool/brainpoolP224t1 + tcId = 857 + + + wycheproof/addsub/brainpoolP224t1/3w + 0x1b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c2,0x6709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1 + + brainpool/brainpoolP224t1 + tcId = 857 + + + wycheproof/addsub/brainpoolP256t1/1s + 0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974855f5 + brainpool/brainpoolP256t1 + tcId = 935 + + + wycheproof/addsub/brainpoolP256t1/1w + 0x2053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b,0x02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245 + + brainpool/brainpoolP256t1 + tcId = 935 + + + wycheproof/addsub/brainpoolP256t1/2s + 0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e8297485675 + brainpool/brainpoolP256t1 + tcId = 936 + + + wycheproof/addsub/brainpoolP256t1/2w + 0x2053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b,0x02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245 + + brainpool/brainpoolP256t1 + tcId = 936 + + + wycheproof/addsub/brainpoolP256t1/3s + 0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e8297485695 + brainpool/brainpoolP256t1 + tcId = 937 + + + wycheproof/addsub/brainpoolP256t1/3w + 0x2053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b,0x02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245 + + brainpool/brainpoolP256t1 + tcId = 937 + + + wycheproof/addsub/brainpoolP256t1/4s + 0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a5 + brainpool/brainpoolP256t1 + tcId = 939 + + + wycheproof/addsub/brainpoolP256t1/4w + 0x2053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b,0x02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245 + + brainpool/brainpoolP256t1 + tcId = 939 + + + wycheproof/addsub/brainpoolP320t1/1s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59233 + brainpool/brainpoolP320t1 + tcId = 1015 + + + wycheproof/addsub/brainpoolP320t1/1w + 0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd + + brainpool/brainpoolP320t1 + tcId = 1015 + + + wycheproof/addsub/brainpoolP320t1/2s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c592b3 + brainpool/brainpoolP320t1 + tcId = 1016 + + + wycheproof/addsub/brainpoolP320t1/2w + 0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd + + brainpool/brainpoolP320t1 + tcId = 1016 + + + wycheproof/addsub/brainpoolP320t1/3s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c592f3 + brainpool/brainpoolP320t1 + tcId = 1017 + + + wycheproof/addsub/brainpoolP320t1/3w + 0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd + + brainpool/brainpoolP320t1 + tcId = 1017 + + + wycheproof/addsub/brainpoolP320t1/4s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59303 + brainpool/brainpoolP320t1 + tcId = 1018 + + + wycheproof/addsub/brainpoolP320t1/4w + 0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd + + brainpool/brainpoolP320t1 + tcId = 1018 + + + wycheproof/addsub/brainpoolP320t1/5s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c5930b + brainpool/brainpoolP320t1 + tcId = 1019 + + + wycheproof/addsub/brainpoolP320t1/5w + 0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd + + brainpool/brainpoolP320t1 + tcId = 1019 + + + wycheproof/addsub/brainpoolP320t1/6s + 0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c5930f + brainpool/brainpoolP320t1 + tcId = 1021 + + + wycheproof/addsub/brainpoolP320t1/6w + 0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd + + brainpool/brainpoolP320t1 + tcId = 1021 + + + wycheproof/addsub/brainpoolP384t1/1s + 0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904652f + brainpool/brainpoolP384t1 + tcId = 1093 + + + wycheproof/addsub/brainpoolP384t1/1w + 0x1e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf,0x88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71 + + brainpool/brainpoolP384t1 + tcId = 1093 + + + wycheproof/addsub/brainpoolP384t1/2s + 0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904654f + brainpool/brainpoolP384t1 + tcId = 1094 + + + wycheproof/addsub/brainpoolP384t1/2w + 0x1e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf,0x88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71 + + brainpool/brainpoolP384t1 + tcId = 1094 + + + wycheproof/addsub/brainpoolP384t1/3s + 0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904655f + brainpool/brainpoolP384t1 + tcId = 1095 + + + wycheproof/addsub/brainpoolP384t1/3w + 0x1e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf,0x88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71 + + brainpool/brainpoolP384t1 + tcId = 1095 + + + wycheproof/addsub/brainpoolP384t1/4s + 0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046563 + brainpool/brainpoolP384t1 + tcId = 1097 + + + wycheproof/addsub/brainpoolP384t1/4w + 0x1e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf,0x88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71 + + brainpool/brainpoolP384t1 + tcId = 1097 + + + wycheproof/addsub/brainpoolP512t1/1s + 0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca9003b + brainpool/brainpoolP512t1 + tcId = 1185 + + + wycheproof/addsub/brainpoolP512t1/1w + 0x242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd079,0x3d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed + + brainpool/brainpoolP512t1 + tcId = 1185 + + + wycheproof/addsub/brainpoolP512t1/2s + 0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca9005b + brainpool/brainpoolP512t1 + tcId = 1186 + + + wycheproof/addsub/brainpoolP512t1/2w + 0x242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd079,0x3d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed + + brainpool/brainpoolP512t1 + tcId = 1186 + + + wycheproof/addsub/brainpoolP512t1/3s + 0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90063 + brainpool/brainpoolP512t1 + tcId = 1187 + + + wycheproof/addsub/brainpoolP512t1/3w + 0x242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd079,0x3d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed + + brainpool/brainpoolP512t1 + tcId = 1187 + + + wycheproof/addsub/brainpoolP512t1/4s + 0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90067 + brainpool/brainpoolP512t1 + tcId = 1189 + + + wycheproof/addsub/brainpoolP512t1/4w + 0x242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd079,0x3d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed + + brainpool/brainpoolP512t1 + tcId = 1189 + + \ No newline at end of file -- cgit v1.3.1 From d22fb876d79dd16cb1f762a732ba8acb6c8b401c Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 25 May 2018 20:56:40 +0200 Subject: Add docs about edge-cases suite and wycheproof data. --- docs/CURVES.md | 7 ++++++- docs/TESTS.md | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/CURVES.md b/docs/CURVES.md index a0454a3..78a5a4c 100644 --- a/docs/CURVES.md +++ b/docs/CURVES.md @@ -71,4 +71,9 @@ Generate manually using [PARI/GP](http://pari.math.u-bordeaux.fr/). ### cofactor Contains curves that are composite order, with points not on the subgroup generated by the generator. -Generated using [ecgen](https://github.com/J08nY/ecgen). \ No newline at end of file +Generated using [ecgen](https://github.com/J08nY/ecgen). + +## Other + +### Wycheproof +Contains some test vectors from the [google/Wycheproof](https://github.com/google/wycheproof) project. \ No newline at end of file diff --git a/docs/TESTS.md b/docs/TESTS.md index d2c3ab5..ebb8150 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -9,8 +9,9 @@ - `twist`* - `degenerate`* - `cofactor`* + - `edge-cases`* -**\*NOTE: The `wrong`, `composite`, `invalid`,`twist`, `cofactor` and `degenerate` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for +**\*NOTE: The `wrong`, `composite`, `invalid`,`twist`, `cofactor`, `edge-cases` and `degenerate` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for confirmation before running, be cautious.** ## Default @@ -132,4 +133,18 @@ during ECDH. For example: ```bash java -jar ECTester.jar -t cofactor +``` + +## Edge-Cases +Tests various inputs to ECDH which may cause an implementation to achieve a certain edge-case state during ECDH. +Some of the data is from the google/Wycheproof project. Tests include [CVE-2017-10176](https://nvd.nist.gov/vuln/detail/CVE-2017-10176) and [CVE-2017-8932](https://nvd.nist.gov/vuln/detail/CVE-2017-8932). + +CVE-2017-10176 was in implementation issue in the SunEC Java library that caused the implementation to reach the point at infinity during ECDH computation. + +CVE-2017-8932 was an implementation issue in the Go standard library, in particular its scalar multiplication algorithm on the +P-256 curve which leaked information about the private key. + +For example: +```bash +java -jar ECTester.jar -t edge-cases ``` \ No newline at end of file -- cgit v1.3.1 From 47e0465f1260e249016b512363b8625418a35ac3 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 27 May 2018 23:44:37 +0200 Subject: Simplify the edge-cases test suite and provide better analysis of results. --- docs/LIBS.md | 8 +-- src/cz/crcs/ectester/common/test/CompoundTest.java | 75 ++++++++++------------ .../ectester/reader/test/CardEdgeCasesSuite.java | 14 ++-- 3 files changed, 47 insertions(+), 50 deletions(-) (limited to 'docs') diff --git a/docs/LIBS.md b/docs/LIBS.md index a1395bc..5c132f7 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -1,6 +1,6 @@ # Libraries with ECC support -Libraries with at least some ECC support: +Popular libraries with at least some ECC support: - [Crypto++](https://cryptopp.com/) - [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/) @@ -20,9 +20,9 @@ Libraries with at least some ECC support: - [Botan](https://botan.randombit.net/) - C++ - Uses blinded(randomized) Montgomery ladder. - - https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2 - - https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc - - https://eprint.iacr.org/2015/657 + - + - + - - ECTester supports v2.4.0 and up. - [libtomcrypt](http://www.libtom.net/LibTomCrypt/) - C diff --git a/src/cz/crcs/ectester/common/test/CompoundTest.java b/src/cz/crcs/ectester/common/test/CompoundTest.java index 2c851b2..607dadb 100644 --- a/src/cz/crcs/ectester/common/test/CompoundTest.java +++ b/src/cz/crcs/ectester/common/test/CompoundTest.java @@ -22,6 +22,24 @@ public class CompoundTest extends Test { } }; + private final static Consumer RUN_GREEDY_ALL = tests -> { + for (Test t : tests) { + t.run(); + if (!t.ok()) { + break; + } + } + }; + + private final static Consumer RUN_GREEDY_ANY = tests -> { + for (Test t : tests) { + t.run(); + if (t.ok()) { + break; + } + } + }; + private CompoundTest(Function resultCallback, Consumer runCallback, Test... tests) { this.resultCallback = resultCallback; this.runCallback = runCallback; @@ -49,7 +67,7 @@ public class CompoundTest extends Test { return new CompoundTest(callback, runCallback, description, tests); } - public static CompoundTest all(Result.ExpectedValue what, Test... all) { + private static CompoundTest expectAll(Result.ExpectedValue what, Consumer runCallback, Test[] all) { return new CompoundTest((tests) -> { for (Test test : tests) { if (!Result.Value.fromExpected(what, test.ok()).ok()) { @@ -57,7 +75,11 @@ public class CompoundTest extends Test { } } return new Result(Result.Value.SUCCESS, "All sub-tests had the expected result."); - }, RUN_ALL, all); + }, runCallback, all); + } + + public static CompoundTest all(Result.ExpectedValue what, Test... all) { + return expectAll(what, RUN_ALL, all); } public static CompoundTest all(Result.ExpectedValue what, String description, Test... all) { @@ -67,21 +89,7 @@ public class CompoundTest extends Test { } public static CompoundTest greedyAll(Result.ExpectedValue what, Test... all) { - return new CompoundTest((tests) -> { - for (Test test : tests) { - if (!Result.Value.fromExpected(what, test.ok()).ok()) { - return new Result(Result.Value.FAILURE, "Some sub-tests did not have the expected result."); - } - } - return new Result(Result.Value.SUCCESS, "All sub-tests had the expected result."); - }, (tests) -> { - for (Test t : tests) { - t.run(); - if (!t.ok()) { - break; - } - } - }, all); + return expectAll(what, RUN_GREEDY_ALL, all); } public static CompoundTest greedyAll(Result.ExpectedValue what, String description, Test... all) { @@ -111,14 +119,7 @@ public class CompoundTest extends Test { } else { return new Result(Result.Value.SUCCESS, "All considered sub-tests had the expected result."); } - }, (tests) -> { - for (Test t : tests) { - t.run(); - if (!t.ok()) { - break; - } - } - }, all); + }, RUN_GREEDY_ALL, all); } public static CompoundTest greedyAllTry(Result.ExpectedValue what, String description, Test... all) { @@ -127,7 +128,7 @@ public class CompoundTest extends Test { return result; } - public static CompoundTest greedyAny(Result.ExpectedValue what, Test... any) { + private static CompoundTest expectAny(Result.ExpectedValue what, Consumer runCallback, Test[] any) { return new CompoundTest((tests) -> { for (Test test : tests) { if (Result.Value.fromExpected(what, test.ok()).ok()) { @@ -135,14 +136,11 @@ public class CompoundTest extends Test { } } return new Result(Result.Value.FAILURE, "None of the sub-tests had the expected result."); - }, (tests) -> { - for (Test t : tests) { - t.run(); - if (t.ok()) { - break; - } - } - }, any); + }, runCallback, any); + } + + public static CompoundTest greedyAny(Result.ExpectedValue what, Test... any) { + return expectAny(what, RUN_GREEDY_ANY, any); } public static CompoundTest greedyAny(Result.ExpectedValue what, String description, Test... any) { @@ -152,14 +150,7 @@ public class CompoundTest extends Test { } public static CompoundTest any(Result.ExpectedValue what, Test... any) { - return new CompoundTest((tests) -> { - for (Test test : tests) { - if (Result.Value.fromExpected(what, test.ok()).ok()) { - return new Result(Result.Value.SUCCESS, "Some sub-tests did have the expected result."); - } - } - return new Result(Result.Value.FAILURE, "None of the sub-tests had the expected result."); - }, RUN_ALL, any); + return expectAny(what, RUN_ALL, any); } public static CompoundTest any(Result.ExpectedValue what, String description, Test... any) { diff --git a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java index ae18f77..0a4515a 100644 --- a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java @@ -39,6 +39,8 @@ public class CardEdgeCasesSuite extends CardTestSuite { String description = null; switch (e.getKey()) { case "addsub": + description = "Tests for addition-subtraction chains."; + break; case "cve_2017_10176": description = "Tests for CVE-2017-10176."; break; @@ -55,8 +57,7 @@ public class CardEdgeCasesSuite extends CardTestSuite { List curveTests = new LinkedList<>(); Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - curveTests.add(allocate); - curveTests.add(set); + Test prepareCurve = CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Prepare curve", allocate, set); List values = c.getValue(); for (EC_KAResult value : values) { @@ -91,10 +92,15 @@ public class CardEdgeCasesSuite extends CardTestSuite { } }); - Test one = CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Test " + id + ".", setPrivkey, setPubkey, ecdhPreTest, ecdh); + Test prepare = CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Prepare", setPrivkey, setPubkey); + Test ka = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do", ecdhPreTest, ecdh); + + Test one = CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Test " + id + ".", prepare, ka); curveTests.add(one); } - groupTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests on " + curve.getId() + ".", curveTests.toArray(new Test[0]))); + + Test curveTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests", curveTests.toArray(new Test[0])); + groupTests.add(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Tests on " + curve.getId() + ".", prepareCurve, curveTest)); } doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, description, groupTests.toArray(new Test[0]))); } -- cgit v1.3.1 From f4063951527fa533d0b59998019b1a800dbc02d0 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 30 May 2018 01:50:23 +0200 Subject: Add basic support for the Crypto++ library. --- build-standalone.xml | 7 + docs/LIBS.md | 5 +- nbproject/reader/project.properties | 2 +- nbproject/standalone/project.properties | 2 +- .../ectester/standalone/ECTesterStandalone.java | 10 +- .../crcs/ectester/standalone/libs/CryptoppLib.java | 20 +++ src/cz/crcs/ectester/standalone/libs/jni/Makefile | 51 ++++--- .../standalone/libs/jni/NativeECPrivateKey.java | 6 + .../standalone/libs/jni/NativeECPublicKey.java | 7 + .../standalone/libs/jni/NativeKeyAgreementSpi.java | 20 ++- .../libs/jni/NativeKeyPairGeneratorSpi.java | 28 ++++ .../standalone/libs/jni/NativeProvider.java | 10 ++ src/cz/crcs/ectester/standalone/libs/jni/botan.cpp | 151 +++++---------------- .../ectester/standalone/libs/jni/cpp_utils.cpp | 24 ++++ .../ectester/standalone/libs/jni/cpp_utils.hpp | 8 +- .../crcs/ectester/standalone/libs/jni/cryptopp.cpp | 121 +++++++++++++++++ src/cz/crcs/ectester/standalone/libs/jni/native.h | 144 ++++++++++++++++++++ 17 files changed, 471 insertions(+), 145 deletions(-) create mode 100644 src/cz/crcs/ectester/standalone/libs/CryptoppLib.java create mode 100644 src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp (limited to 'docs') diff --git a/build-standalone.xml b/build-standalone.xml index dcfb1f3..9d0fa75 100644 --- a/build-standalone.xml +++ b/build-standalone.xml @@ -115,6 +115,13 @@ + + + + + + + diff --git a/docs/LIBS.md b/docs/LIBS.md index 5c132f7..f6d3896 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -2,7 +2,6 @@ Popular libraries with at least some ECC support: - - [Crypto++](https://cryptopp.com/) - [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/) - [mbedTLS](https://tls.mbed.org/) - [Nettle](http://www.lysator.liu.se/~nisse/nettle/) @@ -27,4 +26,6 @@ Popular libraries with at least some ECC support: - [libtomcrypt](http://www.libtom.net/LibTomCrypt/) - C - Uses Jacobian coordinates. - - Sliding window scalar multiplication algorithm. \ No newline at end of file + - Sliding window scalar multiplication algorithm. + - [Crypto++](https://cryptopp.com/) + - C++ \ No newline at end of file diff --git a/nbproject/reader/project.properties b/nbproject/reader/project.properties index b738c2d..8e11520 100644 --- a/nbproject/reader/project.properties +++ b/nbproject/reader/project.properties @@ -6,7 +6,7 @@ annotation.processing.source.output=${build.generated.sources.dir}/ap-source-out application.title=ECTesterReader application.vendor=xsvenda build.classes.dir=${build.dir}/classes -build.classes.excludes=**/*.java,**/*.form,**/*.c,**/*.h,**/*.a,**/*.o,**/Makefile +build.classes.excludes=**/*.java,**/*.form,**/*.c,**/*.cpp,**/*.hpp,**/*.h,**/*.a,**/*.o,**/Makefile # This directory is removed when the project is cleaned: build.dir=build build.generated.dir=${build.dir}/generated diff --git a/nbproject/standalone/project.properties b/nbproject/standalone/project.properties index 355ea58..ee584b2 100644 --- a/nbproject/standalone/project.properties +++ b/nbproject/standalone/project.properties @@ -6,7 +6,7 @@ annotation.processing.source.output=${build.generated.sources.dir}/ap-source-out application.title=ECTesterStandalone application.vendor=xsvenda build.classes.dir=${build.dir}/classes -build.classes.excludes=**/*.java,**/*.form,**/*.c,**/*.h,**/*.a,**/*.o,**/Makefile +build.classes.excludes=**/*.java,**/*.form,**/*.c,**/*.cpp,**/*.hpp,**/*.h,**/*.a,**/*.o,**/Makefile # This directory is removed when the project is cleaned: build.dir=build build.generated.dir=${build.dir}/generated diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java index 60a33f3..5a7b79a 100644 --- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -66,7 +66,7 @@ import java.util.stream.Collectors; * @version v0.2.0 */ public class ECTesterStandalone { - private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib()}; + private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib()}; private Config cfg; private Options opts = new Options(); @@ -218,19 +218,19 @@ public class ECTesterStandalone { System.out.println("\t- " + lib.name()); Set kpgs = lib.getKPGs(); if (!kpgs.isEmpty()) { - System.out.println("\t\t- KeyPairGenerators: " + String.join(",", kpgs.stream().map(KeyPairGeneratorIdent::getName).collect(Collectors.toList()))); + System.out.println("\t\t- KeyPairGenerators: " + String.join(", ", kpgs.stream().map(KeyPairGeneratorIdent::getName).collect(Collectors.toList()))); } Set eckas = lib.getKAs(); if (!eckas.isEmpty()) { - System.out.println("\t\t- KeyAgreements: " + String.join(",", eckas.stream().map(KeyAgreementIdent::getName).collect(Collectors.toList()))); + System.out.println("\t\t- KeyAgreements: " + String.join(", ", eckas.stream().map(KeyAgreementIdent::getName).collect(Collectors.toList()))); } Set sigs = lib.getSigs(); if (!sigs.isEmpty()) { - System.out.println("\t\t- Signatures: " + String.join(",", sigs.stream().map(SignatureIdent::getName).collect(Collectors.toList()))); + System.out.println("\t\t- Signatures: " + String.join(", ", sigs.stream().map(SignatureIdent::getName).collect(Collectors.toList()))); } Set curves = lib.getCurves(); if (!curves.isEmpty()) { - System.out.println("\t\t- Curves: " + String.join(",", curves)); + System.out.println("\t\t- Curves: " + String.join(", ", curves)); } System.out.println(); } diff --git a/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java b/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java new file mode 100644 index 0000000..5112d7d --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java @@ -0,0 +1,20 @@ +package cz.crcs.ectester.standalone.libs; + +import java.security.Provider; +import java.util.Set; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CryptoppLib extends NativeECLibrary { + + public CryptoppLib() { + super("cryptopp_provider", "cryptopp"); + } + + @Override + native Provider createProvider(); + + @Override + public native Set getCurves(); +} diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile index 732ab20..beeefdf 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile @@ -1,31 +1,32 @@ ifeq ($(JAVA_HOME),) -ifeq ($(OS),Windows_NT) -which = $(shell where $1) -else -which = $(shell which $1) -endif -JAVAC ?= $(realpath $(call which,javac)) -JAVA_HOME = $(abspath $(dir $(JAVAC))..) + ifeq ($(OS),Windows_NT) + which = $(shell where $1) + else + which = $(shell which $1) + endif + JAVAC ?= $(realpath $(call which,javac)) + JAVA_HOME = $(abspath $(dir $(JAVAC))..) endif ifneq ($(JAVA_HOME),) -JNI_INCLUDEDIR ?= $(JAVA_HOME)/include + JNI_INCLUDEDIR ?= $(JAVA_HOME)/include endif ifeq ($(JNI_INCLUDEDIR),) -$(error could not determine JNI include dir, try specifying either JAVA_HOME or JNI_INCLUDEDIR) + $(error Could not determine JNI include dir. Try specifying either JAVA_HOME or JNI_INCLUDEDIR.) endif TARGETTRIPLET := $(shell $(CC) -dumpmachine) + ifeq ($(JNI_PLATFORM),) -ifeq ($(findstring mingw,$(TARGETTRIPLET)),mingw) -JNI_PLATFORM:= win32 -else -ifeq ($(findstring linux,$(TARGETTRIPLET)),linux) -JNI_PLATFORM:= linux -# add more checks here -endif -endif + ifeq ($(findstring mingw,$(TARGETTRIPLET)),mingw) + JNI_PLATFORM:= win32 + else + ifeq ($(findstring linux,$(TARGETTRIPLET)),linux) + JNI_PLATFORM:= linux + # add more checks here + endif + endif endif JNI_PLATFORMINCLUDEDIR ?= $(JNI_INCLUDEDIR)/$(JNI_PLATFORM) @@ -40,8 +41,9 @@ CFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. CXXFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. -all: tomcrypt_provider.so botan_provider.so +all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so +# Common utils c_utils.o: c_utils.c $(CC) $(CFLAGS) -c $< @@ -49,6 +51,7 @@ cpp_utils.o: cpp_utils.cpp $(CXX) $(CXXFLAGS) -c $< +# Libtomcrypt shim tomcrypt_provider.so: tomcrypt.o c_utils.o $(CC) -fPIC -g -shared -o $@ $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt) @@ -56,11 +59,21 @@ tomcrypt.o: tomcrypt.c $(CC) -DLTM_DESC $(shell pkg-config --cflags libtomcrypt) $(CFLAGS) -c $< +# Botan-2 shim botan_provider.so: botan.o cpp_utils.o $(CXX) -fPIC -g -shared -o $@ $^ -L. $(shell pkg-config --libs botan-2) botan.o: botan.cpp - $(CXX) $(shell pkg-config --cflags botan-2) $(CFLAGS) -c $< + $(CXX) $(shell pkg-config --cflags botan-2) $(CXXFLAGS) -c $< + + +# Crypto++ shim +cryptopp_provider.so: cryptopp.o cpp_utils.o + $(CXX) -fPIC -g -shared -o $@ $^ -L. $(shell pkg-config --libs libcrypto++) + +cryptopp.o: cryptopp.cpp + $(CXX) $(shell pkg-config --cflags libcrypto++) $(CXXFLAGS) -c $< + clean: rm -rf *.o diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java index 22e5329..a209fa1 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java @@ -65,4 +65,10 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { super(keyData, params); } } + + public static class Cryptopp extends Raw { + public Cryptopp(byte[] keyData, ECParameterSpec params) { + super(keyData, params); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java index 8fc4747..f53cd26 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java @@ -3,6 +3,7 @@ package cz.crcs.ectester.standalone.libs.jni; import cz.crcs.ectester.common.util.ECUtil; import org.bouncycastle.util.Arrays; +import javax.swing.event.AncestorEvent; import java.security.interfaces.ECPublicKey; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; @@ -66,4 +67,10 @@ public abstract class NativeECPublicKey implements ECPublicKey { super(keyData, params); } } + + public static class Cryptopp extends ANSIX962 { + public Cryptopp(byte[] keyData, ECParameterSpec params) { + super(keyData, params); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java index f3242ba..fc1b8d7 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java @@ -78,7 +78,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { @Override protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException { - // TODO: This is dangerous! + // TODO: This is dangerous/not correct ! Need to actually implement KDF1 and KDF2 here probably. return new SecretKeySpec(engineGenerateSecret(), algorithm); } @@ -93,6 +93,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { public abstract static class Botan extends NativeKeyAgreementSpi { private String type; + public Botan(String type) { this.type = type; } @@ -136,4 +137,21 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { super("ECDHwithSHA512KDF"); } } + + public abstract static class Cryptopp extends NativeKeyAgreementSpi { + private String type; + + public Cryptopp(String type) { + this.type = type; + } + + @Override + native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); + } + + public static class CryptoppECDH extends Cryptopp { + public CryptoppECDH() { + super("ECDH"); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java index 9461251..54aa37e 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java @@ -120,4 +120,32 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { super("ECGDSA"); } } + + public static abstract class Cryptopp extends NativeKeyPairGeneratorSpi { + private String type; + + public Cryptopp(String type) { + this.type = type; + initialize(256, new SecureRandom()); + } + + @Override + native boolean keysizeSupported(int keysize); + + @Override + native boolean paramsSupported(AlgorithmParameterSpec params); + + @Override + native KeyPair generate(int keysize, SecureRandom random); + + @Override + native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random); + } + + public static class CryptoppECDH extends Botan { + + public CryptoppECDH() { + super("ECDH"); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java index a0689d6..593295e 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java @@ -39,4 +39,14 @@ public abstract class NativeProvider extends Provider { @Override native void setup(); } + + public static class Cryptopp extends NativeProvider { + + public Cryptopp(String name, double version, String info) { + super(name, version, info); + } + + @Override + native void setup(); + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp index 3bb43a2..6a1e6d6 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp +++ b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp @@ -52,117 +52,38 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createP JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Botan_setup(JNIEnv *env, jobject self){ jmethodID provider_put = env->GetMethodID(provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - jstring ecdh = env->NewStringUTF("KeyPairGenerator.ECDH"); - jstring ecdh_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECDH"); - env->CallObjectMethod(self, provider_put, ecdh, ecdh_value); - - jstring ecdsa = env->NewStringUTF("KeyPairGenerator.ECDSA"); - jstring ecdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECDSA"); - env->CallObjectMethod(self, provider_put, ecdsa, ecdsa_value); - - jstring eckcdsa = env->NewStringUTF("KeyPairGenerator.ECKCDSA"); - jstring eckcdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECKCDSA"); - env->CallObjectMethod(self, provider_put, eckcdsa, eckcdsa_value); - - jstring ecgdsa = env->NewStringUTF("KeyPairGenerator.ECGDSA"); - jstring ecgdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECGDSA"); - env->CallObjectMethod(self, provider_put, ecgdsa, ecgdsa_value); - - jstring ecdh_ka = env->NewStringUTF("KeyAgreement.ECDH"); - jstring ecdh_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDH"); - env->CallObjectMethod(self, provider_put, ecdh_ka, ecdh_ka_value); - - jstring ecdh_sha1_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA1KDF"); - jstring ecdh_sha1_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA1KDF"); - env->CallObjectMethod(self, provider_put, ecdh_sha1_ka, ecdh_sha1_ka_value); - - jstring ecdh_sha224_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA224KDF"); - jstring ecdh_sha224_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA224KDF"); - env->CallObjectMethod(self, provider_put, ecdh_sha224_ka, ecdh_sha224_ka_value); - - jstring ecdh_sha256_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA256KDF"); - jstring ecdh_sha256_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA256KDF"); - env->CallObjectMethod(self, provider_put, ecdh_sha256_ka, ecdh_sha256_ka_value); - - jstring ecdh_sha384_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA384KDF"); - jstring ecdh_sha384_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA384KDF"); - env->CallObjectMethod(self, provider_put, ecdh_sha384_ka, ecdh_sha384_ka_value); - - jstring ecdh_sha512_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA512KDF"); - jstring ecdh_sha512_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA512KDF"); - env->CallObjectMethod(self, provider_put, ecdh_sha512_ka, ecdh_sha512_ka_value); - - jstring ecdsa_sig = env->NewStringUTF("Signature.NONEwithECDSA"); - jstring ecdsa_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithNONE"); - env->CallObjectMethod(self, provider_put, ecdsa_sig, ecdsa_sig_value); - - jstring ecdsa_sha1_sig = env->NewStringUTF("Signature.SHA1withECDSA"); - jstring ecdsa_sha1_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA1"); - env->CallObjectMethod(self, provider_put, ecdsa_sha1_sig, ecdsa_sha1_sig_value); - - jstring ecdsa_sha224_sig = env->NewStringUTF("Signature.SHA224withECDSA"); - jstring ecdsa_sha224_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA224"); - env->CallObjectMethod(self, provider_put, ecdsa_sha224_sig, ecdsa_sha224_sig_value); - - jstring ecdsa_sha256_sig = env->NewStringUTF("Signature.SHA256withECDSA"); - jstring ecdsa_sha256_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA256"); - env->CallObjectMethod(self, provider_put, ecdsa_sha256_sig, ecdsa_sha256_sig_value); - - jstring ecdsa_sha384_sig = env->NewStringUTF("Signature.SHA384withECDSA"); - jstring ecdsa_sha384_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA384"); - env->CallObjectMethod(self, provider_put, ecdsa_sha384_sig, ecdsa_sha384_sig_value); - - jstring ecdsa_sha512_sig = env->NewStringUTF("Signature.SHA512withECDSA"); - jstring ecdsa_sha512_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA512"); - env->CallObjectMethod(self, provider_put, ecdsa_sha512_sig, ecdsa_sha512_sig_value); + add_kpg(env, "ECDH", "BotanECDH", self, provider_put); + add_kpg(env, "ECDSA", "BotanECDSA", self, provider_put); + add_kpg(env, "ECKCDSA", "BotanECKCDSA", self, provider_put); + add_kpg(env, "ECGDSA", "BotanECGDSA", self, provider_put); + + add_ka(env, "ECDH", "BotanECDH", self, provider_put); + add_ka(env, "ECDHwithSHA1KDF", "BotanECDHwithSHA1KDF", self, provider_put); + add_ka(env, "ECDHwithSHA224KDF", "BotanECDHwithSHA224KDF", self, provider_put); + add_ka(env, "ECDHwithSHA256KDF", "BotanECDHwithSHA256KDF", self, provider_put); + add_ka(env, "ECDHwithSHA384KDF", "BotanECDHwithSHA384KDF", self, provider_put); + add_ka(env, "ECDHwithSHA512KDF", "BotanECDHwithSHA512KDF", self, provider_put); + + add_sig(env, "NONEwithECDSA", "BotanECDSAwithNONE", self, provider_put); + add_sig(env, "SHA1withECDSA", "BotanECDSAwithSHA1", self, provider_put); + add_sig(env, "SHA224withECDSA", "BotanECDSAwithSHA224", self, provider_put); + add_sig(env, "SHA256withECDSA", "BotanECDSAwithSHA256", self, provider_put); + add_sig(env, "SHA384withECDSA", "BotanECDSAwithSHA384", self, provider_put); + add_sig(env, "SHA512withECDSA", "BotanECDSAwithSHA512", self, provider_put); + + add_sig(env, "NONEwithECKCDSA", "BotanECKCDSAwithNONE", self, provider_put); + add_sig(env, "SHA1withECKCDSA", "BotanECKCDSAwithSHA1", self, provider_put); + add_sig(env, "SHA224withECKCDSA", "BotanECKCDSAwithSHA224", self, provider_put); + add_sig(env, "SHA256withECKCDSA", "BotanECKCDSAwithSHA256", self, provider_put); + add_sig(env, "SHA384withECKCDSA", "BotanECKCDSAwithSHA384", self, provider_put); + add_sig(env, "SHA512withECKCDSA", "BotanECKCDSAwithSHA512", self, provider_put); - jstring eckcdsa_sig = env->NewStringUTF("Signature.NONEwithECKCDSA"); - jstring eckcdsa_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithNONE"); - env->CallObjectMethod(self, provider_put, eckcdsa_sig, eckcdsa_sig_value); - - jstring eckcdsa_sha1_sig = env->NewStringUTF("Signature.SHA1withECKCDSA"); - jstring eckcdsa_sha1_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA1"); - env->CallObjectMethod(self, provider_put, eckcdsa_sha1_sig, eckcdsa_sha1_sig_value); - - jstring eckcdsa_sha224_sig = env->NewStringUTF("Signature.SHA224withECKCDSA"); - jstring eckcdsa_sha224_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA224"); - env->CallObjectMethod(self, provider_put, eckcdsa_sha224_sig, eckcdsa_sha224_sig_value); - - jstring eckcdsa_sha256_sig = env->NewStringUTF("Signature.SHA256withECKCDSA"); - jstring eckcdsa_sha256_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA256"); - env->CallObjectMethod(self, provider_put, eckcdsa_sha256_sig, eckcdsa_sha256_sig_value); - - jstring eckcdsa_sha384_sig = env->NewStringUTF("Signature.SHA384withECKCDSA"); - jstring eckcdsa_sha384_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA384"); - env->CallObjectMethod(self, provider_put, eckcdsa_sha384_sig, eckcdsa_sha384_sig_value); - - jstring eckcdsa_sha512_sig = env->NewStringUTF("Signature.SHA512withECKCDSA"); - jstring eckcdsa_sha512_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA512"); - env->CallObjectMethod(self, provider_put, eckcdsa_sha512_sig, eckcdsa_sha512_sig_value); - - jstring ecgdsa_sig = env->NewStringUTF("Signature.NONEwithECGDSA"); - jstring ecgdsa_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithNONE"); - env->CallObjectMethod(self, provider_put, ecgdsa_sig, ecgdsa_sig_value); - - jstring ecgdsa_sha1_sig = env->NewStringUTF("Signature.SHA1withECGDSA"); - jstring ecgdsa_sha1_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA1"); - env->CallObjectMethod(self, provider_put, ecgdsa_sha1_sig, ecgdsa_sha1_sig_value); - - jstring ecgdsa_sha224_sig = env->NewStringUTF("Signature.SHA224withECGDSA"); - jstring ecgdsa_sha224_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA224"); - env->CallObjectMethod(self, provider_put, ecgdsa_sha224_sig, ecgdsa_sha224_sig_value); - - jstring ecgdsa_sha256_sig = env->NewStringUTF("Signature.SHA256withECGDSA"); - jstring ecgdsa_sha256_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA256"); - env->CallObjectMethod(self, provider_put, ecgdsa_sha256_sig, ecgdsa_sha256_sig_value); - - jstring ecgdsa_sha384_sig = env->NewStringUTF("Signature.SHA384withECGDSA"); - jstring ecgdsa_sha384_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA384"); - env->CallObjectMethod(self, provider_put, ecgdsa_sha384_sig, ecgdsa_sha384_sig_value); - - jstring ecgdsa_sha512_sig = env->NewStringUTF("Signature.SHA512withECGDSA"); - jstring ecgdsa_sha512_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA512"); - env->CallObjectMethod(self, provider_put, ecgdsa_sha512_sig, ecgdsa_sha512_sig_value); + add_sig(env, "NONEwithECGDSA", "BotanECGDSAwithNONE", self, provider_put); + add_sig(env, "SHA1withECGDSA", "BotanECGDSAwithSHA1", self, provider_put); + add_sig(env, "SHA224withECGDSA", "BotanECGDSAwithSHA224", self, provider_put); + add_sig(env, "SHA256withECGDSA", "BotanECGDSAwithSHA256", self, provider_put); + add_sig(env, "SHA384withECGDSA", "BotanECGDSAwithSHA384", self, provider_put); + add_sig(env, "SHA512withECGDSA", "BotanECGDSAwithSHA512", self, provider_put); init_classes(env, "Botan"); } @@ -173,18 +94,18 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ * Signature: ()Ljava/util/Set; */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self){ - jclass hash_set_class = env->FindClass("java/util/TreeSet"); + jclass set_class = env->FindClass("java/util/TreeSet"); - jmethodID hash_set_ctr = env->GetMethodID(hash_set_class, "", "()V"); - jmethodID hash_set_add = env->GetMethodID(hash_set_class, "add", "(Ljava/lang/Object;)Z"); + jmethodID set_ctr = env->GetMethodID(set_class, "", "()V"); + jmethodID set_add = env->GetMethodID(set_class, "add", "(Ljava/lang/Object;)Z"); - jobject result = env->NewObject(hash_set_class, hash_set_ctr); + jobject result = env->NewObject(set_class, set_ctr); const std::set& curves = Botan::EC_Group::known_named_groups(); for (auto it = curves.begin(); it != curves.end(); ++it) { std::string curve_name = *it; jstring name_str = env->NewStringUTF(curve_name.c_str()); - env->CallBooleanMethod(result, hash_set_add, name_str); + env->CallBooleanMethod(result, set_add, name_str); } return result; diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp index cef4bfe..2e93a71 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp +++ b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp @@ -56,4 +56,28 @@ void init_classes(JNIEnv *env, std::string lib_name) { void throw_new(JNIEnv *env, const std::string& klass, const std::string& message) { jclass clazz = env->FindClass(klass.c_str()); env->ThrowNew(clazz, message.c_str()); +} + +static void add_provider_property(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method) { + jstring type_str = env->NewStringUTF(type.c_str()); + jstring class_str = env->NewStringUTF(klass.c_str()); + env->CallObjectMethod(provider, put_method, type_str, class_str); +} + +void add_kpg(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method) { + const std::string full_type = "KeyPairGenerator." + type; + const std::string full_class = "cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$" + klass; + add_provider_property(env, full_type, full_class, provider, put_method); +} + +void add_ka(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method) { + const std::string full_type = "KeyAgreement." + type; + const std::string full_class = "cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$" + klass; + add_provider_property(env, full_type, full_class, provider, put_method); +} + +void add_sig(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method) { + const std::string full_type = "Signature." + type; + const std::string full_class = "cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$" + klass; + add_provider_property(env, full_type, full_class, provider, put_method); } \ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp index bbca521..f647bd6 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp +++ b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp @@ -26,4 +26,10 @@ void init_classes(JNIEnv *env, std::string lib_name); /** * Throw a new exception of class with message. */ -void throw_new(JNIEnv *env, const std::string& klass, const std::string& message); \ No newline at end of file +void throw_new(JNIEnv *env, const std::string& klass, const std::string& message); + +void add_kpg(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method); + +void add_ka(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method); + +void add_sig(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method); \ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp new file mode 100644 index 0000000..0432247 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp @@ -0,0 +1,121 @@ +#include "native.h" + +#include +using std::cout; +using std::cerr; +using std::endl; + +#include +#include +using std::string; + +#include +using std::runtime_error; + +#include +using std::exit; + +#include "cryptopp/osrng.h" +using CryptoPP::AutoSeededRandomPool; +using CryptoPP::AutoSeededX917RNG; + +#include "cryptopp/aes.h" +using CryptoPP::AES; + +#include "cryptopp/eccrypto.h" +using CryptoPP::ECP; +using CryptoPP::ECDH; +using CryptoPP::DL_GroupParameters_EC; + +#include "cryptopp/secblock.h" +using CryptoPP::SecByteBlock; + +#include "cryptopp/oids.h" +using CryptoPP::OID; + +// ASN1 is a namespace, not an object +#include "cryptopp/asn.h" +using namespace CryptoPP::ASN1; + +#include "cryptopp/integer.h" +using CryptoPP::Integer; + + +#include "cpp_utils.hpp" + +static jclass provider_class; + + +/* + * Class: cz_crcs_ectester_standalone_libs_CryptoppLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider(JNIEnv *env, jobject self) { + /* Create the custom provider. */ + jclass local_provider_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeProvider$Cryptopp"); + provider_class = (jclass) env->NewGlobalRef(local_provider_class); + + jmethodID init = env->GetMethodID(local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V"); + + std::string lib_name = "Crypto++"; + + int lib_version = CRYPTOPP_VERSION; + std::string info_str = std::to_string(lib_version); + std::stringstream ss; + ss << lib_name << " "; + ss << info_str[0]; + for (int i = 1; i < info_str.size(); ++i) { + ss << "." << info_str[i]; + } + + jstring name = env->NewStringUTF(lib_name.c_str()); + double version = lib_version / 100; + jstring info = env->NewStringUTF(ss.str().c_str()); + + return env->NewObject(provider_class, init, name, version, info); +} + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Cryptopp_setup(JNIEnv *env, jobject self){ + jmethodID provider_put = env->GetMethodID(provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + + init_classes(env, "Cryptopp"); +} + +/* + * Class: cz_crcs_ectester_standalone_libs_CryptoppLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves(JNIEnv *env, jobject self){ + jclass set_class = env->FindClass("java/util/TreeSet"); + + jmethodID set_ctr = env->GetMethodID(set_class, "", "()V"); + jmethodID set_add = env->GetMethodID(set_class, "add", "(Ljava/lang/Object;)Z"); + + jobject result = env->NewObject(set_class, set_ctr); + + OID it = OID(); + do { + it = DL_GroupParameters_EC::GetNextRecommendedParametersOID(it); + if (it == OID()) { + break; + } + const std::vector& oid_values = it.GetValues(); + std::stringstream ss; + for (size_t i = 0; i < oid_values.size(); ++i) { + if(i != 0) + ss << "."; + ss << std::to_string(oid_values[i]); + } + jstring name_str = env->NewStringUTF(ss.str().c_str()); + env->CallBooleanMethod(result, set_add, name_str); + } while (true); + + return result; +} \ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h index d714b39..61c4411 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -342,3 +342,147 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } #endif #endif +/* Header for class cz_crcs_ectester_standalone_libs_CryptoppLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_CryptoppLib +#define _Included_cz_crcs_ectester_standalone_libs_CryptoppLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_CryptoppLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_CryptoppLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 1421746759512286392LL +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 4112578634029874840LL +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -4298000515446427739LL +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Cryptopp_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp + * Method: keysizeSupported + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported + (JNIEnv *, jobject, jint); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp + * Method: paramsSupported + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_paramsSupported + (JNIEnv *, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp + * Method: generate + * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__ILjava_security_SecureRandom_2 + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp + * Method: generate + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 + (JNIEnv *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp + * Method: generateSecret + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Cryptopp_generateSecret + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif -- cgit v1.3.1 From 07cfc81f909ebeee6ea88a5671749bc44e5c6769 Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 28 Jun 2018 17:15:30 +0200 Subject: Add descriptions to composite curve data. --- docs/TESTS.md | 4 + src/cz/crcs/ectester/data/composite/curves.xml | 87 +++++++++++++--------- .../ectester/reader/test/CardWrongCurvesSuite.java | 2 +- 3 files changed, 56 insertions(+), 37 deletions(-) (limited to 'docs') diff --git a/docs/TESTS.md b/docs/TESTS.md index ebb8150..c62234b 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -65,6 +65,10 @@ This test suite also does some additional tests with corrupting the field parame - p = 1 - p = q^2; q prime - p = q * s; q and s prime + - G = infinity + - G = random point not on curve + - r = some prime (and \[r\]G != infinity) + - r = some composite number (and \[r\]G != infinity) - F2m: - e1 = e2 = e3 = 0 - m < e1 < e2 < e3 diff --git a/src/cz/crcs/ectester/data/composite/curves.xml b/src/cz/crcs/ectester/data/composite/curves.xml index 4d6a16a..a1abe2e 100644 --- a/src/cz/crcs/ectester/data/composite/curves.xml +++ b/src/cz/crcs/ectester/data/composite/curves.xml @@ -6,83 +6,98 @@ 128 prime composite128.csv - - - small/composite128 - 128 - prime - composite128_small.csv + r = order = 0x03 * 0x05 * 0x3b * 0x3a107e02cd073c8e24bf55730f1733 whole/composite160 160 prime composite160.csv - - - small/composite160 - 160 - prime - composite160_small.csv + r = order = 0x02 * 0x03 * 0x6b * 0x1ee99b75143833bbc11d409601c25f9566a001 whole/composite192 192 prime composite192.csv - - - small/composite192 - 192 - prime - composite192_small.csv + r = order = 0x02 * 0x03 * 0x05 * 0x13 * 0x19bc3c00e2a7ad9e40d12e5d9e29a2b5ce80b3a3e84295 whole/composite224 224 prime composite224.csv - - - small/composite224 - 224 - prime - composite224_small.csv + r = order = 0x02 * 0x03 * 0x1d * 0x1538e6a6dc906d724a7bf51c77bce9d46865bd92d8bca01f887405 whole/composite256 256 prime composite256.csv - - - small/composite256 - 256 - prime - composite256_small.csv + r = order = 0x02 * 0x05 * 0x11 * 0x1382cadcdd2b90b90b81eda82433bf574b5d8f5654dcc62341c7e967f2e811 whole/composite384 384 prime composite384.csv - - - small/composite384 - 384 - prime - composite384_small.csv + r = order = 0x05 * 0x0b * 0x3d * 0xb16aa7dc50145337cf1b2f38018ccb5cf44c22a2f7d7c22bbe5c572d2cb9a04cb1081357c6a1c97cc39ab62596867 whole/composite521 521 prime composite521.csv + r = order = 0x02 * 0x05 * 0x1f * 0x4a5aac4fac3ea253b66c3e650f5173b30467f28b8e841d37ce69bb0831a5939ad3dd082b750577ec4592d4d58916c87a9b732d8ddae435c26f8f779d2467f50f + + + + small/composite128 + 128 + prime + composite128_small.csv + r = 0x03 + + + small/composite160 + 160 + prime + composite160_small.csv + r = 0x03 + + + small/composite192 + 192 + prime + composite192_small.csv + r = 0x03 + + + small/composite224 + 224 + prime + composite224_small.csv + r = 0x03 + + + small/composite256 + 256 + prime + composite256_small.csv + r = 0x05 + + + small/composite384 + 384 + prime + composite384_small.csv + r = 0x05 small/composite521 521 prime composite521_small.csv + r = 0x05 \ No newline at end of file diff --git a/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java index f95a386..8b648b9 100644 --- a/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java @@ -111,8 +111,8 @@ public class CardWrongCurvesSuite extends CardTestSuite { Test resetSetup = CompoundTest.all(ExpectedValue.SUCCESS, "Reset keypair.", set.clone()); - Test zeroG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, EC_Consts.TRANSFORMATION_INFINITY), "Set G = inifnity.", "ECDH with G = infinity."); Test randomG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, (short) (EC_Consts.TRANSFORMATION_FULLRANDOM | EC_Consts.TRANSFORMATION_04_MASK)), "Set G = random non-point/point-like.", "ECDH with non-point G."); + Test zeroG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, EC_Consts.TRANSFORMATION_INFINITY), "Set G = inifnity.", "ECDH with G = infinity."); Test wrongG = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted G parameter.", zeroG, randomG); byte[] originalR = new byte[keyLength]; -- cgit v1.3.1 From 632ba7f154bd90b3528ed39b2bc01cb2cfa10dd0 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 30 Jun 2018 18:27:41 +0200 Subject: Add more composite tests. --- docs/TESTS.md | 5 ++- .../ectester/data/composite/composite128_rg0.csv | 1 + .../ectester/data/composite/composite160_rg0.csv | 1 + .../ectester/data/composite/composite192_rg0.csv | 1 + .../ectester/data/composite/composite224_rg0.csv | 1 + .../ectester/data/composite/composite256_pq.csv | 2 +- .../ectester/data/composite/composite256_pq1.csv | 2 +- .../ectester/data/composite/composite256_pq2.csv | 2 +- .../ectester/data/composite/composite256_rg0.csv | 1 + .../ectester/data/composite/composite256_small.csv | 2 +- .../crcs/ectester/data/composite/composite384.csv | 2 +- .../ectester/data/composite/composite384_small.csv | 2 +- .../crcs/ectester/data/composite/composite521.csv | 2 +- .../ectester/data/composite/composite521_small.csv | 2 +- src/cz/crcs/ectester/data/composite/curves.xml | 40 ++++++++++++++++++++++ .../reader/test/CardCompositeCurvesSuite.java | 6 +++- 16 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 src/cz/crcs/ectester/data/composite/composite128_rg0.csv create mode 100644 src/cz/crcs/ectester/data/composite/composite160_rg0.csv create mode 100644 src/cz/crcs/ectester/data/composite/composite192_rg0.csv create mode 100644 src/cz/crcs/ectester/data/composite/composite224_rg0.csv create mode 100644 src/cz/crcs/ectester/data/composite/composite256_rg0.csv (limited to 'docs') diff --git a/docs/TESTS.md b/docs/TESTS.md index c62234b..59bd27b 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -59,7 +59,7 @@ Tests on a category of wrong curves. These curves are not really curves as they - non-prime field in the prime-field case - reducible polynomial as the field polynomial in the binary case -This test suite also does some additional tests with corrupting the field parameter: +This test suite also does some additional tests with corrupting the parameters: - Fp: - p = 0 - p = 1 @@ -87,6 +87,9 @@ Tests using curves that don't have a prime order/nearly prime order. These tests should generally fail, a success here implies the card will use a non-secure curve if such curve is set by the applet. Operations over such curves are susceptible to small-subgroup attacks. + - r = p * q + - \[r\]G = infinity but r != |G|, so |G| divides r + For example: ```bash java -jar ECTester.jar -t composite diff --git a/src/cz/crcs/ectester/data/composite/composite128_rg0.csv b/src/cz/crcs/ectester/data/composite/composite128_rg0.csv new file mode 100644 index 0000000..2e039f4 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/composite128_rg0.csv @@ -0,0 +1 @@ +0xee6b3964632807cf11b8b9dba1b4f099,0x1fd6f78c0303652c5b7de184a4744f98,0x2da1b3253571565989f3b72b865a3e27,0x6ef5b1d42abdbd6f44bcf4d64504927c,0x73e82c27b93032b7a7a15111d1569bb3,0xee6b3964632807cd9c885b5658f1a7c7,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite160_rg0.csv b/src/cz/crcs/ectester/data/composite/composite160_rg0.csv new file mode 100644 index 0000000..e6a1a95 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/composite160_rg0.csv @@ -0,0 +1 @@ +0x919cf0a89ca7a8ea2f61156ea4b3100a2a357477,0x75cd1f1c32f1e5d2b2d54db103b22d296de34722,0x3177d3e2f79c884a0b1a6e74d9843c3a52e794de,0x706deef87d4593bbeaa70bc2609e1d8c0e2e0c10,0x64df2537d395da2e0cb8c7e340426b64699cf325,0x919cf0a89ca7a8ea2f626ab2ab86ff4a074a5d51,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite192_rg0.csv b/src/cz/crcs/ectester/data/composite/composite192_rg0.csv new file mode 100644 index 0000000..a55a994 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/composite192_rg0.csv @@ -0,0 +1 @@ +0xa261fff62647eebf810a404f0c80a971dd7c7838fdc52b5b,0x87502ebb62d26e1eca06c434f8ef069dfb2c287d6183750c,0x4ad6ce1f16e1bfc3d40f0027d787aeadb53846d69099a883,0x6366613b66339fa580f390d630ccf9b535437229aa8b61cd,0x2abab8c0e803a3612c7a7fbcb47e06fd8ef42a7a7d8c380f,0xa261fff62647eebf810a404f23ba4db93199e2e02ccffdfd,0x1 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite224_rg0.csv b/src/cz/crcs/ectester/data/composite/composite224_rg0.csv new file mode 100644 index 0000000..835676d --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/composite224_rg0.csv @@ -0,0 +1 @@ +0xa0dccd401872aa37c279e2469a08d97d559addb6fc870a1766f80e6f,0x393797f1d924dc63c761d4497086d09284a922a5517c07f93f3a075c,0x54f4673322854dafc1241b66192134ea9e18f8849c45660b793abb97,0x1b189f3372946c9cbb421a60bc3a0a06d16cf3ce043781ada561834c,0x57e00f270dbc56c6c86946dcb6c6ab12133d168609c588b6960c357f,0xa0dccd401872aa37c279e2469a0791ea2f15e32a10632ec07cf3ff97,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite256_pq.csv b/src/cz/crcs/ectester/data/composite/composite256_pq.csv index 8a59520..380f756 100644 --- a/src/cz/crcs/ectester/data/composite/composite256_pq.csv +++ b/src/cz/crcs/ectester/data/composite/composite256_pq.csv @@ -1 +1 @@ -0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x4c4765a35cb2de9cc548d4dd47778b70395d023c4bf112f4bc820431502384e9,0x25bffa1f9ae1af10177f32abf13d3f607e78415c89676eeb13330098c9794503,0xf75e78a6e2acb23d6317e57258287c021fa26f10c359320ee8758b4e1f2c605d,0x1 \ No newline at end of file +0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x4c4765a35cb2de9cc548d4dd47778b70395d023c4bf112f4bc820431502384e9,0x25bffa1f9ae1af10177f32abf13d3f607e78415c89676eeb13330098c9794503,0xf75e78a6e2acb23d6317e57258287c021fa26f10c359320ee8758b4e1f2c605d,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite256_pq1.csv b/src/cz/crcs/ectester/data/composite/composite256_pq1.csv index 8012893..e3d5b42 100644 --- a/src/cz/crcs/ectester/data/composite/composite256_pq1.csv +++ b/src/cz/crcs/ectester/data/composite/composite256_pq1.csv @@ -1 +1 @@ -0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x93d1f4d02d6f0d2ea7b80f7095e70e731bcf66fb8118e7698a16eab45aadcaa4,0x51dccaa47e35062383e4878625bf2116be5413c34a1b964c7547f65297f0bc04,0x743bc7ea193d40db,0x1 \ No newline at end of file +0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x93d1f4d02d6f0d2ea7b80f7095e70e731bcf66fb8118e7698a16eab45aadcaa4,0x51dccaa47e35062383e4878625bf2116be5413c34a1b964c7547f65297f0bc04,0x000000000000000000000000000000000000000000000000743bc7ea193d40db,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite256_pq2.csv b/src/cz/crcs/ectester/data/composite/composite256_pq2.csv index 25b57af..c67eaa7 100644 --- a/src/cz/crcs/ectester/data/composite/composite256_pq2.csv +++ b/src/cz/crcs/ectester/data/composite/composite256_pq2.csv @@ -1 +1 @@ -0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x93d1f4d02d6f0d2ea7b80f7095e70e731bcf66fb8118e7698a16eab45aadcaa4,0x3db7c6ee2d24d142ee0ec56f3ba0a606d099debb66a765e3926a5aa19539a2c3,0x220d23234534b240aac0efa70a3bc44e046c2431ad5a32d27,0x1 \ No newline at end of file +0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x93d1f4d02d6f0d2ea7b80f7095e70e731bcf66fb8118e7698a16eab45aadcaa4,0x3db7c6ee2d24d142ee0ec56f3ba0a606d099debb66a765e3926a5aa19539a2c3,0x000000000000000220d23234534b240aac0efa70a3bc44e046c2431ad5a32d27,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite256_rg0.csv b/src/cz/crcs/ectester/data/composite/composite256_rg0.csv new file mode 100644 index 0000000..0c2d123 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/composite256_rg0.csv @@ -0,0 +1 @@ +0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x93d1f4d02d6f0d2ea7b80f7095e70e731bcf66fb8118e7698a16eab45aadcaa4,0x51dccaa47e35062383e4878625bf2116be5413c34a1b964c7547f65297f0bc04,0xf75e78a6e2acb23d6317e57258287c021fa26f10c359320ee8758b4e1f2c605d,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite256_small.csv b/src/cz/crcs/ectester/data/composite/composite256_small.csv index a28e62e..58c0a75 100644 --- a/src/cz/crcs/ectester/data/composite/composite256_small.csv +++ b/src/cz/crcs/ectester/data/composite/composite256_small.csv @@ -1 +1 @@ -0xdc42862158cdcfc8fbe8c4ec28b02e0e12624ebc15f6486163df218253e1b953,0x01f355375dac7e69cc12c22ce747782bf998252f1c9c9c983273bc2b7e721461,0x22098140e10d5d88bcc96a558500a022d0252bfbe438d3475ef2d90261fe3b1f,0x8ca20dd1fa045339a171513fb1daa25fa7439e4b97c129c6039e4b9abbac1532,0xb565bde8fe9831f0bce07d70784dc1b7064c443b54b5e96408c1942e30437cc3,0x0000000000000000000000000000000000000000000000000000000000000005,0x1 \ No newline at end of file +0xdc42862158cdcfc8fbe8c4ec28b02e0e12624ebc15f6486163df218253e1b953,0x01f355375dac7e69cc12c22ce747782bf998252f1c9c9c983273bc2b7e721461,0x22098140e10d5d88bcc96a558500a022d0252bfbe438d3475ef2d90261fe3b1f,0x8ca20dd1fa045339a171513fb1daa25fa7439e4b97c129c6039e4b9abbac1532,0xb565bde8fe9831f0bce07d70784dc1b7064c443b54b5e96408c1942e30437cc3,0x0000000000000000000000000000000000000000000000000000000000000005,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite384.csv b/src/cz/crcs/ectester/data/composite/composite384.csv index 7516301..4e9d058 100644 --- a/src/cz/crcs/ectester/data/composite/composite384.csv +++ b/src/cz/crcs/ectester/data/composite/composite384.csv @@ -1 +1 @@ -0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189da10277423d7381fd4671fc706ff1dce6f8513317842fb655b,0x6c64adff869b4e0b9f0dd35945b24e3ab389232b1e506a71306e389dddbf43ec6c73d290fab04976da246fd77a7e28dd,0x4004c33e4f8b4de57064543802ca11810c79aa9990796d5750dba07f3e4e98f3dd18b3abe052208741149c3ad0fe6f56,0x39bf2e7d67ad506e074e04c1b73a4add511b0579cdae07bd6c025c703ee31ff33c0445c2cb10e465f0f453d996751e4e,0x667ec38866be3e87229e31e6dabc2444e2603e8118c0316e592571e9a904423e4792c18c0360ae57fcdaec87901d2e0b,0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189db347c42a7d0924b7cd1414d57f582a4b96177c911e9bb3ddd,0x1 \ No newline at end of file +0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189da10277423d7381fd4671fc706ff1dce6f8513317842fb655b,0x6c64adff869b4e0b9f0dd35945b24e3ab389232b1e506a71306e389dddbf43ec6c73d290fab04976da246fd77a7e28dd,0x4004c33e4f8b4de57064543802ca11810c79aa9990796d5750dba07f3e4e98f3dd18b3abe052208741149c3ad0fe6f56,0x39bf2e7d67ad506e074e04c1b73a4add511b0579cdae07bd6c025c703ee31ff33c0445c2cb10e465f0f453d996751e4e,0x667ec38866be3e87229e31e6dabc2444e2603e8118c0316e592571e9a904423e4792c18c0360ae57fcdaec87901d2e0b,0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189db347c42a7d0924b7cd1414d57f582a4b96177c911e9bb3ddd,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite384_small.csv b/src/cz/crcs/ectester/data/composite/composite384_small.csv index 470704d..00b643b 100644 --- a/src/cz/crcs/ectester/data/composite/composite384_small.csv +++ b/src/cz/crcs/ectester/data/composite/composite384_small.csv @@ -1 +1 @@ -0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189da10277423d7381fd4671fc706ff1dce6f8513317842fb655b,0x6c64adff869b4e0b9f0dd35945b24e3ab389232b1e506a71306e389dddbf43ec6c73d290fab04976da246fd77a7e28dd,0x4004c33e4f8b4de57064543802ca11810c79aa9990796d5750dba07f3e4e98f3dd18b3abe052208741149c3ad0fe6f56,0x5136c182f03241ec87e6eec1728c1fb2d6b2ddcd4d9abf2a110c337419c4ec7cc8386b7b9ea9f5cb18b0f3c2a78e6489,0x9130cb73f8064fddb24d8c6a216b57fe99df93bcc82c93343617a5246ca1643fe57a06d6112a1791d1bd3643fbd9c041,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005,0x1 \ No newline at end of file +0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189da10277423d7381fd4671fc706ff1dce6f8513317842fb655b,0x6c64adff869b4e0b9f0dd35945b24e3ab389232b1e506a71306e389dddbf43ec6c73d290fab04976da246fd77a7e28dd,0x4004c33e4f8b4de57064543802ca11810c79aa9990796d5750dba07f3e4e98f3dd18b3abe052208741149c3ad0fe6f56,0x5136c182f03241ec87e6eec1728c1fb2d6b2ddcd4d9abf2a110c337419c4ec7cc8386b7b9ea9f5cb18b0f3c2a78e6489,0x9130cb73f8064fddb24d8c6a216b57fe99df93bcc82c93343617a5246ca1643fe57a06d6112a1791d1bd3643fbd9c041,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite521.csv b/src/cz/crcs/ectester/data/composite/composite521.csv index 0cf36e7..8681273 100644 --- a/src/cz/crcs/ectester/data/composite/composite521.csv +++ b/src/cz/crcs/ectester/data/composite/composite521.csv @@ -1 +1 @@ -0x01c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b3690e2f82b38a684e823a257b3d5c4c2d7c34bfcb937fe5658c77247b28bc90c6af,0x00852cf32173a9b3a8a2316bbe6ba0b98efcc41247a17a8aead02ccc7cb90870daccd10a44e9385abf0d0ae175fa03c0facab1d2069b79795f36d10ce25430676805,0x0174e20e49d5970117cdfc61c0a0ae062519c0c4d577f42e0d3f1cd443732b8e62deb34922a4a6d85b8b7f6df61dadffec95c17babbfaf5c57598033be0b1a44e32f,0x01b1dbc5bd175cbd8699895698b10d047853679f048261094854134de1d6a81ffdd1cc31ede64293c9bee543ad2113c164bd1da92f5c3aa7ba7f0378bdb58251d870,0x0188b8c020cc1504eedb4fb859e40b8031cb26d9273efa2578bf7da01db994cf2a5cf2780b9a7ff6d33210b962ae20c56f71b7fa2b36deef33d7d675c6136acd73c1,0x1c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b36ec447771e871c188d3f04a4e407f1d659335dd0e351bd7f3f76a639726d6dc0d2,0x1 \ No newline at end of file +0x01c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b3690e2f82b38a684e823a257b3d5c4c2d7c34bfcb937fe5658c77247b28bc90c6af,0x00852cf32173a9b3a8a2316bbe6ba0b98efcc41247a17a8aead02ccc7cb90870daccd10a44e9385abf0d0ae175fa03c0facab1d2069b79795f36d10ce25430676805,0x0174e20e49d5970117cdfc61c0a0ae062519c0c4d577f42e0d3f1cd443732b8e62deb34922a4a6d85b8b7f6df61dadffec95c17babbfaf5c57598033be0b1a44e32f,0x01b1dbc5bd175cbd8699895698b10d047853679f048261094854134de1d6a81ffdd1cc31ede64293c9bee543ad2113c164bd1da92f5c3aa7ba7f0378bdb58251d870,0x0188b8c020cc1504eedb4fb859e40b8031cb26d9273efa2578bf7da01db994cf2a5cf2780b9a7ff6d33210b962ae20c56f71b7fa2b36deef33d7d675c6136acd73c1,0x1c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b36ec447771e871c188d3f04a4e407f1d659335dd0e351bd7f3f76a639726d6dc0d2,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/composite521_small.csv b/src/cz/crcs/ectester/data/composite/composite521_small.csv index f065b9f..15df9c8 100644 --- a/src/cz/crcs/ectester/data/composite/composite521_small.csv +++ b/src/cz/crcs/ectester/data/composite/composite521_small.csv @@ -1 +1 @@ -0x01c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b3690e2f82b38a684e823a257b3d5c4c2d7c34bfcb937fe5658c77247b28bc90c6af,0x00852cf32173a9b3a8a2316bbe6ba0b98efcc41247a17a8aead02ccc7cb90870daccd10a44e9385abf0d0ae175fa03c0facab1d2069b79795f36d10ce25430676805,0x0174e20e49d5970117cdfc61c0a0ae062519c0c4d577f42e0d3f1cd443732b8e62deb34922a4a6d85b8b7f6df61dadffec95c17babbfaf5c57598033be0b1a44e32f,0x00a4b42ad90c0e3f7e342d8d661b4d5162ab7928b4938ab660b2e6fea3213c5d4b420123f65141a8eb7b4a46173bfce6ea1577df94f6f934f72d459c4dd3c0ef038e,0x003316c4b6c5c6b3ab3eee7f1ff365cce6045fdc43d4e6c64efa7789f2626676b47b488e6612d291d60d4a788ddd2e8b1aa8bfff02e105a285532a20ac08fa1088e7,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005,0x1 \ No newline at end of file +0x01c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b3690e2f82b38a684e823a257b3d5c4c2d7c34bfcb937fe5658c77247b28bc90c6af,0x00852cf32173a9b3a8a2316bbe6ba0b98efcc41247a17a8aead02ccc7cb90870daccd10a44e9385abf0d0ae175fa03c0facab1d2069b79795f36d10ce25430676805,0x0174e20e49d5970117cdfc61c0a0ae062519c0c4d577f42e0d3f1cd443732b8e62deb34922a4a6d85b8b7f6df61dadffec95c17babbfaf5c57598033be0b1a44e32f,0x00a4b42ad90c0e3f7e342d8d661b4d5162ab7928b4938ab660b2e6fea3213c5d4b420123f65141a8eb7b4a46173bfce6ea1577df94f6f934f72d459c4dd3c0ef038e,0x003316c4b6c5c6b3ab3eee7f1ff365cce6045fdc43d4e6c64efa7789f2626676b47b488e6612d291d60d4a788ddd2e8b1aa8bfff02e105a285532a20ac08fa1088e7,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005,0x01 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/curves.xml b/src/cz/crcs/ectester/data/composite/curves.xml index 1eddbea..8cec330 100644 --- a/src/cz/crcs/ectester/data/composite/curves.xml +++ b/src/cz/crcs/ectester/data/composite/curves.xml @@ -123,6 +123,14 @@ r = 0x3c1be1d1dd7edf84b8013495 + + rg0/composite128 + 128 + prime + composite128_rg0.csv + |G| divides r(so [r]G = infinity), but r != |G| = 0x03f76917eb + + pq/composite160 160 @@ -145,6 +153,14 @@ r = 0x4d7041e1dbf10b42f48c4f + + rg0/composite160 + 160 + prime + composite160_rg0.csv + |G| divides r(so [r]G = infinity), but r != |G| = 0x0af2407f270b81f45f + + pq/composite192 192 @@ -166,6 +182,14 @@ composite192_pq2.csv r = 0x35efd8bad55038e6bd22db8b805 + + + rg0/composite192 + 192 + prime + composite192_rg0.csv + |G| divides r(so [r]G = infinity), but r != |G| = 0x302b72431ff070e7e06799 + pq/composite224 @@ -189,6 +213,14 @@ r = 0x6a99de2a928e8f227e7a2ed33a555f24ef5 + + rg0/composite224 + 224 + prime + composite224_rg0.csv + |G| divides r(so [r]G = infinity), but r != |G| = 0x1824ec370e405bfb5024db + + pq/composite256 256 @@ -210,4 +242,12 @@ composite256_pq2.csv r = 0x220d23234534b240aac0efa70a3bc44e046c2431ad5a32d27 + + + rg0/composite256 + 256 + prime + composite256_rg0.csv + |G| divides r(so [r]G = infinity), but r != |G| = 0x743bc7ea193d40db + \ No newline at end of file diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java index d474638..2b3724c 100644 --- a/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java @@ -3,7 +3,6 @@ package cz.crcs.ectester.reader.test; import cz.crcs.ectester.applet.ECTesterApplet; import cz.crcs.ectester.applet.EC_Consts; import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_KAResult; import cz.crcs.ectester.common.ec.EC_Key; import cz.crcs.ectester.common.output.TestWriter; import cz.crcs.ectester.common.test.CompoundTest; @@ -71,6 +70,11 @@ public class CardCompositeCurvesSuite extends CardTestSuite { */ List pqCurves = groupList.stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue(); testGroup(pqCurves, null, ExpectedValue.ANY, "", ""); + + /* Also test rg0 curves. + */ + List rg0Curves = groupList.stream().filter((e) -> e.getKey().equals("rg0")).findFirst().get().getValue(); + testGroup(rg0Curves, null, ExpectedValue.ANY, "", ""); } private void testGroup(List curves, String testName, ExpectedValue dhValue, String ok, String nok) throws Exception { -- cgit v1.3.1 From 050541a45d16597099e86b14d0fdf4e123a8e93e Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 3 Jul 2018 15:03:31 +0200 Subject: Update docs and README. --- README.md | 2 ++ docs/CURVES.md | 10 ++++++++++ docs/TESTS.md | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/README.md b/README.md index 7b280bb..9305e3c 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,8 @@ See `java -jar ECTesterReader.jar -h` for more. constants. -sig,--sig-type Set Signature object [type], corresponds to JC.Signature constants. + -C,--color Print stuff with color, requires ANSI + terminal. ``` ### Actions diff --git a/docs/CURVES.md b/docs/CURVES.md index 78a5a4c..a9b8b68 100644 --- a/docs/CURVES.md +++ b/docs/CURVES.md @@ -33,6 +33,16 @@ GOST R 34.10-2001: RFC5832 curves. [Source](https://tools.ietf.org/html/rfc5832) +### Barreto-Naehrig +Barreto-Naehrig curves from: A Family of Implementation-Friendly BN Elliptic Curves + +[Source](https://eprint.iacr.org/2010/429.pdf) + +### Other +An assortment of some other curves. +Montgomery curves transformed into short Weierstrass form from +Curve25519 transformed into short Weierstrass form. + ## Generated diff --git a/docs/TESTS.md b/docs/TESTS.md index 59bd27b..5ec3b63 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -135,7 +135,8 @@ java -jar ECTester.jar -t degenerate ## Cofactor Tests whether the card correctly rejects points that lie on the curve but not on the subgroup generated by the specified generator -during ECDH. +during ECDH. Does this with curves where the cofactor subgroup has small order, then with curves that have order equal to the product +of two large primes, sets the generator with order of one prime and tries points on the subgroup of the other prime order. For example: ```bash -- cgit v1.3.1 From 50244cd3ff01ad997b5900883ffbc95dbba1154f Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 4 Jul 2018 17:00:05 +0200 Subject: Add supersingular curves, do some tests over supersingular and Barreto-Naehrig curves. --- docs/CURVES.md | 6 + docs/TESTS.md | 9 + src/cz/crcs/ectester/data/categories.xml | 5 + src/cz/crcs/ectester/data/supersingular/curves.xml | 32 ++++ src/cz/crcs/ectester/data/supersingular/ss128.csv | 1 + src/cz/crcs/ectester/data/supersingular/ss192.csv | 1 + src/cz/crcs/ectester/data/supersingular/ss224.csv | 1 + src/cz/crcs/ectester/data/supersingular/ss256.csv | 1 + src/cz/crcs/ectester/reader/ECTesterReader.java | 28 +-- .../reader/test/CardCompositeCurvesSuite.java | 98 ---------- .../ectester/reader/test/CardCompositeSuite.java | 98 ++++++++++ .../reader/test/CardDegenerateCurvesSuite.java | 55 ------ .../ectester/reader/test/CardDegenerateSuite.java | 55 ++++++ .../reader/test/CardInvalidCurvesSuite.java | 75 -------- .../ectester/reader/test/CardInvalidSuite.java | 75 ++++++++ .../crcs/ectester/reader/test/CardMiscSuite.java | 54 ++++++ .../crcs/ectester/reader/test/CardTwistSuite.java | 69 +++++++ .../ectester/reader/test/CardTwistTestSuite.java | 69 ------- .../ectester/reader/test/CardWrongCurvesSuite.java | 203 --------------------- .../crcs/ectester/reader/test/CardWrongSuite.java | 203 +++++++++++++++++++++ 20 files changed, 626 insertions(+), 512 deletions(-) create mode 100644 src/cz/crcs/ectester/data/supersingular/curves.xml create mode 100644 src/cz/crcs/ectester/data/supersingular/ss128.csv create mode 100644 src/cz/crcs/ectester/data/supersingular/ss192.csv create mode 100644 src/cz/crcs/ectester/data/supersingular/ss224.csv create mode 100644 src/cz/crcs/ectester/data/supersingular/ss256.csv delete mode 100644 src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java create mode 100644 src/cz/crcs/ectester/reader/test/CardCompositeSuite.java delete mode 100644 src/cz/crcs/ectester/reader/test/CardDegenerateCurvesSuite.java create mode 100644 src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java delete mode 100644 src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java create mode 100644 src/cz/crcs/ectester/reader/test/CardInvalidSuite.java create mode 100644 src/cz/crcs/ectester/reader/test/CardMiscSuite.java create mode 100644 src/cz/crcs/ectester/reader/test/CardTwistSuite.java delete mode 100644 src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java delete mode 100644 src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java create mode 100644 src/cz/crcs/ectester/reader/test/CardWrongSuite.java (limited to 'docs') diff --git a/docs/CURVES.md b/docs/CURVES.md index a9b8b68..a417035 100644 --- a/docs/CURVES.md +++ b/docs/CURVES.md @@ -41,6 +41,7 @@ Barreto-Naehrig curves from: A Family of Implementation-Friendly BN Elliptic Cur ### Other An assortment of some other curves. Montgomery curves transformed into short Weierstrass form from + Curve25519 transformed into short Weierstrass form. @@ -83,6 +84,11 @@ Contains curves that are composite order, with points not on the subgroup genera Generated using [ecgen](https://github.com/J08nY/ecgen). +### supersingular +Contains supersingular curves, over F_p with order equal to p + 1. These have embedding degree equal to 2. + +Generated using [ecgen](https://github.com/J08nY/ecgen). + ## Other ### Wycheproof diff --git a/docs/TESTS.md b/docs/TESTS.md index 5ec3b63..4d71ea6 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -3,6 +3,7 @@ - `default` - `test-vectors` - `compression` + - `miscellaneous` - `wrong`* - `composite`* - `invalid`* @@ -155,4 +156,12 @@ P-256 curve which leaked information about the private key. For example: ```bash java -jar ECTester.jar -t edge-cases +``` + +## Miscellaneous +Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves and Barreto-Naehrig curves with small embedding degree and CM discriminant. + +For example: +```bash +java -jar ECTester.jar -t miscellaneous ``` \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/categories.xml b/src/cz/crcs/ectester/data/categories.xml index e725db0..38ce683 100644 --- a/src/cz/crcs/ectester/data/categories.xml +++ b/src/cz/crcs/ectester/data/categories.xml @@ -89,4 +89,9 @@ wycheproof Test cases from google Wycheproof project: https://github.com/google/wycheproof + + supersingular + supersingular + Some supersingular curves, over F_p with order equal to p + 1. + \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/supersingular/curves.xml b/src/cz/crcs/ectester/data/supersingular/curves.xml new file mode 100644 index 0000000..186a8a7 --- /dev/null +++ b/src/cz/crcs/ectester/data/supersingular/curves.xml @@ -0,0 +1,32 @@ + + + + ss128 + 128 + prime + ss128.csv + Supersingular curve + + + ss192 + 192 + prime + ss192.csv + Supersingular curve + + + ss224 + 224 + prime + ss224.csv + Supersingular curve + + + ss256 + 256 + prime + ss256.csv + Supersingular curve + + \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/supersingular/ss128.csv b/src/cz/crcs/ectester/data/supersingular/ss128.csv new file mode 100644 index 0000000..9dd4f13 --- /dev/null +++ b/src/cz/crcs/ectester/data/supersingular/ss128.csv @@ -0,0 +1 @@ +0x9ad6ed2af5bd6f3a9ac1d052ea17b2a9,0x8a3fe60aedb247e20a2d0c4a07de4d37,0x10970720080b27589094c408e2396572,0x563804cbd66f054434143af1e3ec6eaf,0x42af7ba7a078ef8fa3c0f253d1ccc16a,0x4d6b76957adeb79d4d60e829750bd955,0x02 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/supersingular/ss192.csv b/src/cz/crcs/ectester/data/supersingular/ss192.csv new file mode 100644 index 0000000..0c8ae8b --- /dev/null +++ b/src/cz/crcs/ectester/data/supersingular/ss192.csv @@ -0,0 +1 @@ +0x8c4dbc0e122afdeb466c2b7c3321e72531ac1cd8435f5159,0x64ff701953d8a795e3d9fa41a85eb2bd355479744198ae6c,0x274e4bf4be5256556292313a8ac33467fc57a36401c6a2ed,0x6c39b62a8665aca35dc1669dd483a1e881c65557bbed7f8c,0x1f90241e9bdb361251343bf4cb1ff19545e1e0fff2c8f235,0x4626de0709157ef5a33615be1990f39298d60e6c21afa8ad,0x02 \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/supersingular/ss224.csv b/src/cz/crcs/ectester/data/supersingular/ss224.csv new file mode 100644 index 0000000..01eaa35 --- /dev/null +++ b/src/cz/crcs/ectester/data/supersingular/ss224.csv @@ -0,0 +1 @@ +0xa52f9550f18b8475c5cddd1232428b0c6138aa8704759eab7916f839,0x35186ffe96c8460148b9070efdde881f68647ff48a93854966ebf457,0x701725525ac33e747d14d603346402ecf8d42a9279e21962122b03e2,0x726e4342d936e7c3f004d36b5a703ca35d000014e70bceb1e956f7cc,0x9b3785caa9b028340c564ec4e7450229b7a0b16bc7185c78d852e2a6,0x1084c221b1c126d893c7c94e9ea0411ad685aaa71a0bc31125b57f39,0x0a \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/supersingular/ss256.csv b/src/cz/crcs/ectester/data/supersingular/ss256.csv new file mode 100644 index 0000000..47a8174 --- /dev/null +++ b/src/cz/crcs/ectester/data/supersingular/ss256.csv @@ -0,0 +1 @@ +0xf9cde8953b26ab31fe1b135266d2f9187e3d9df982880f05cc80f1998b9b0c8d,0xdf0a21f2f4d03d6ca2e151406e17cc1f0300287a348bc4452d7320db6138269e,0x1ac3c6a246566dc55b39c211f8bb2cf97b3d757f4dfc4ac09f0dd0be2a62e5ef,0x3c52f9e66b5c180923ac7bfb7f88f0162ee1dca122aa8dda1e8de3e044cb55a6,0x89c2f4437118d2edb0021706feef5a4419150afd7d1c3b7401eee93c2e547264,0x7ce6f44a9d935598ff0d89a933697c8c3f1ecefcc1440782e64078ccc5cd8647,0x02 \ No newline at end of file diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java index ab022dd..89cfca1 100644 --- a/src/cz/crcs/ectester/reader/ECTesterReader.java +++ b/src/cz/crcs/ectester/reader/ECTesterReader.java @@ -273,7 +273,7 @@ public class ECTesterReader { actions.addOption(Option.builder("ln").longOpt("list-named").desc("Print the list of supported named curves and keys.").hasArg().argName("what").optionalArg(true).build()); actions.addOption(Option.builder("e").longOpt("export").desc("Export the defaut curve parameters of the card(if any).").build()); actions.addOption(Option.builder("g").longOpt("generate").desc("Generate [amount] of EC keys.").hasArg().argName("amount").optionalArg(true).build()); - actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. [test_suite]:\n- default:\n- compression:\n- invalid:\n- twist:\n- degenerate:\n- cofactor:\n- wrong:\n- composite:\n- test-vectors:\n- edge-cases:").hasArg().argName("test_suite").optionalArg(true).build()); + actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. [test_suite]:\n- default:\n- compression:\n- invalid:\n- twist:\n- degenerate:\n- cofactor:\n- wrong:\n- composite:\n- test-vectors:\n- edge-cases:\n- miscellaneous:").hasArg().argName("test_suite").optionalArg(true).build()); actions.addOption(Option.builder("dh").longOpt("ecdh").desc("Do EC KeyAgreement (ECDH...), [count] times.").hasArg().argName("count").optionalArg(true).build()); actions.addOption(Option.builder("dsa").longOpt("ecdsa").desc("Sign data with ECDSA, [count] times.").hasArg().argName("count").optionalArg(true).build()); actions.addOption(Option.builder("ls").longOpt("list-suites").desc("List supported test suites.").build()); @@ -332,13 +332,14 @@ public class ECTesterReader { new CardDefaultSuite(null, null, null), new CardTestVectorSuite(null, null, null), new CardCompressionSuite(null, null, null), - new CardWrongCurvesSuite(null, null, null), - new CardDegenerateCurvesSuite(null, null, null), + new CardWrongSuite(null, null, null), + new CardDegenerateSuite(null, null, null), new CardCofactorSuite(null, null, null), - new CardCompositeCurvesSuite(null, null, null), - new CardInvalidCurvesSuite(null, null, null), + new CardCompositeSuite(null, null, null), + new CardInvalidSuite(null, null, null), new CardEdgeCasesSuite(null, null, null), - new CardTwistTestSuite(null, null, null)}; + new CardTwistSuite(null, null, null), + new CardMiscSuite(null, null, null)}; for (CardTestSuite suite : suites) { System.out.println(" - " + Colors.bold(suite.getName())); for (String line : suite.getDescription()) { @@ -457,6 +458,9 @@ public class ECTesterReader { case "compression": suite = new CardCompressionSuite(writer, cfg, cardManager); break; + case "miscellaneous": + suite = new CardMiscSuite(writer, cfg, cardManager); + break; default: // These run are dangerous, prompt before them. System.out.println("The test you selected (" + cfg.testSuite + ") is potentially dangerous."); @@ -472,19 +476,19 @@ public class ECTesterReader { } switch (cfg.testSuite) { case "wrong": - suite = new CardWrongCurvesSuite(writer, cfg, cardManager); + suite = new CardWrongSuite(writer, cfg, cardManager); break; case "composite": - suite = new CardCompositeCurvesSuite(writer, cfg, cardManager); + suite = new CardCompositeSuite(writer, cfg, cardManager); break; case "invalid": - suite = new CardInvalidCurvesSuite(writer, cfg, cardManager); + suite = new CardInvalidSuite(writer, cfg, cardManager); break; case "degenerate": - suite = new CardDegenerateCurvesSuite(writer, cfg, cardManager); + suite = new CardDegenerateSuite(writer, cfg, cardManager); break; case "twist": - suite = new CardTwistTestSuite(writer, cfg, cardManager); + suite = new CardTwistSuite(writer, cfg, cardManager); break; case "cofactor": suite = new CardCofactorSuite(writer, cfg, cardManager); @@ -824,7 +828,7 @@ public class ECTesterReader { } testSuite = cli.getOptionValue("test", "default").toLowerCase(); - String[] tests = new String[]{"default", "composite", "compression", "invalid", "degenerate", "test-vectors", "wrong", "twist", "cofactor", "edge-cases"}; + String[] tests = new String[]{"default", "composite", "compression", "invalid", "degenerate", "test-vectors", "wrong", "twist", "cofactor", "edge-cases", "miscellaneous"}; if (!Arrays.asList(tests).contains(testSuite)) { System.err.println(Colors.error("Unknown test suite " + testSuite + ". Should be one of: " + Arrays.toString(tests))); return false; diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java deleted file mode 100644 index 2b3724c..0000000 --- a/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java +++ /dev/null @@ -1,98 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardCompositeCurvesSuite extends CardTestSuite { - - public CardCompositeCurvesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "composite", "The composite suite runs ECDH over curves with composite order. This should generally fail, as using such a curve is unsafe."); - } - - @Override - protected void runTests() throws Exception { - /* Do the default run with the public keys set to provided smallorder keys - * over composite order curves. Essentially small subgroup attacks. - * These should fail, the curves aren't safe so that if the computation with - * a small order public key succeeds the private key modulo the public key order - * is revealed. - */ - Map keys = EC_Store.getInstance().getObjects(EC_Key.class, "composite"); - List>> mappedKeys = EC_Store.mapKeyToCurve(keys.values()); - for (Map.Entry> curveKeys : mappedKeys) { - EC_Curve curve = curveKeys.getKey(); - List tests = new LinkedList<>(); - Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); - if (!allocate.ok()) { - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocate)); - continue; - } - tests.add(allocate); - for (EC_Key key : curveKeys.getValue()) { - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, 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, 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."); - - tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", " + key.getDesc(), set, generate, ecdh)); - } - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ".", tests.toArray(new Test[0]))); - new Command.Cleanup(this.card).send(); - } - - /* Also test having a G of small order, so small R. - */ - Map results = EC_Store.getInstance().getObjects(EC_Curve.class, "composite"); - List>> groupList = EC_Store.mapToPrefix(results.values()); - List smallRCurves = groupList.stream().filter((e) -> e.getKey().equals("small")).findFirst().get().getValue(); - testGroup(smallRCurves, "Small generator order", ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a small order generator.", "Card incorrectly does ECDH over a small order generator."); - - /* Also test having a G of large but composite order, R = p * q, - */ - List pqCurves = groupList.stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue(); - testGroup(pqCurves, null, ExpectedValue.ANY, "", ""); - - /* Also test rg0 curves. - */ - List rg0Curves = groupList.stream().filter((e) -> e.getKey().equals("rg0")).findFirst().get().getValue(); - testGroup(rg0Curves, null, ExpectedValue.ANY, "", ""); - } - - private void testGroup(List curves, String testName, ExpectedValue dhValue, String ok, String nok) throws Exception { - for (EC_Curve curve : curves) { - 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_BOTH), ExpectedValue.ANY); - Test ecdh = 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), dhValue, ok, nok); - - String description; - if (testName == null) { - description = curve.getDesc() + " test of " + curve.getId() + "."; - } else { - description = testName + " test of " + curve.getId() + "."; - } - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, description, allocate, set, generate, ecdh)); - new Command.Cleanup(this.card).send(); - } - - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java new file mode 100644 index 0000000..0d4d2e0 --- /dev/null +++ b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java @@ -0,0 +1,98 @@ +package cz.crcs.ectester.reader.test; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Curve; +import cz.crcs.ectester.common.ec.EC_Key; +import cz.crcs.ectester.common.output.TestWriter; +import cz.crcs.ectester.common.test.CompoundTest; +import cz.crcs.ectester.common.test.Test; +import cz.crcs.ectester.common.util.CardUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.reader.CardMngr; +import cz.crcs.ectester.reader.ECTesterReader; +import cz.crcs.ectester.reader.command.Command; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static cz.crcs.ectester.common.test.Result.ExpectedValue; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CardCompositeSuite extends CardTestSuite { + + public CardCompositeSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { + super(writer, cfg, cardManager, "composite", "The composite suite runs ECDH over curves with composite order. This should generally fail, as using such a curve is unsafe."); + } + + @Override + protected void runTests() throws Exception { + /* Do the default run with the public keys set to provided smallorder keys + * over composite order curves. Essentially small subgroup attacks. + * These should fail, the curves aren't safe so that if the computation with + * a small order public key succeeds the private key modulo the public key order + * is revealed. + */ + Map keys = EC_Store.getInstance().getObjects(EC_Key.class, "composite"); + List>> mappedKeys = EC_Store.mapKeyToCurve(keys.values()); + for (Map.Entry> curveKeys : mappedKeys) { + EC_Curve curve = curveKeys.getKey(); + List tests = new LinkedList<>(); + Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); + if (!allocate.ok()) { + doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocate)); + continue; + } + tests.add(allocate); + for (EC_Key key : curveKeys.getValue()) { + Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, 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, 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."); + + tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", " + key.getDesc(), set, generate, ecdh)); + } + doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ".", tests.toArray(new Test[0]))); + new Command.Cleanup(this.card).send(); + } + + /* Also test having a G of small order, so small R. + */ + Map results = EC_Store.getInstance().getObjects(EC_Curve.class, "composite"); + List>> groupList = EC_Store.mapToPrefix(results.values()); + List smallRCurves = groupList.stream().filter((e) -> e.getKey().equals("small")).findFirst().get().getValue(); + testGroup(smallRCurves, "Small generator order", ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a small order generator.", "Card incorrectly does ECDH over a small order generator."); + + /* Also test having a G of large but composite order, R = p * q, + */ + List pqCurves = groupList.stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue(); + testGroup(pqCurves, null, ExpectedValue.ANY, "", ""); + + /* Also test rg0 curves. + */ + List rg0Curves = groupList.stream().filter((e) -> e.getKey().equals("rg0")).findFirst().get().getValue(); + testGroup(rg0Curves, null, ExpectedValue.ANY, "", ""); + } + + private void testGroup(List curves, String testName, ExpectedValue dhValue, String ok, String nok) throws Exception { + for (EC_Curve curve : curves) { + 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_BOTH), ExpectedValue.ANY); + Test ecdh = 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), dhValue, ok, nok); + + String description; + if (testName == null) { + description = curve.getDesc() + " test of " + curve.getId() + "."; + } else { + description = testName + " test of " + curve.getId() + "."; + } + doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, description, allocate, set, generate, ecdh)); + new Command.Cleanup(this.card).send(); + } + + } +} diff --git a/src/cz/crcs/ectester/reader/test/CardDegenerateCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardDegenerateCurvesSuite.java deleted file mode 100644 index 0cc9186..0000000 --- a/src/cz/crcs/ectester/reader/test/CardDegenerateCurvesSuite.java +++ /dev/null @@ -1,55 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -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.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardDegenerateCurvesSuite extends CardTestSuite { - - public CardDegenerateCurvesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "degenerate", "The degenerate suite tests whether the card rejects points outside of the curve during ECDH.", - "The tested points lie on a part of the plane for which some Edwards, Hessian and Huff form addition formulas work."); - } - - @Override - protected void runTests() throws Exception { - Map pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "degenerate"); - List>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry> e : curveList) { - EC_Curve curve = e.getKey(); - List keys = e.getValue(); - - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); - - Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); - - List 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, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten()); - ecdhTests.add(CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve.")); - } - Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with degenerate public points", ecdhTests.toArray(new Test[0])); - - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId(), prepare, ecdh)); - new Command.Cleanup(this.card).send(); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java new file mode 100644 index 0000000..7483b2b --- /dev/null +++ b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java @@ -0,0 +1,55 @@ +package cz.crcs.ectester.reader.test; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Curve; +import cz.crcs.ectester.common.ec.EC_Key; +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.data.EC_Store; +import cz.crcs.ectester.reader.CardMngr; +import cz.crcs.ectester.reader.ECTesterReader; +import cz.crcs.ectester.reader.command.Command; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CardDegenerateSuite extends CardTestSuite { + + public CardDegenerateSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { + super(writer, cfg, cardManager, "degenerate", "The degenerate suite tests whether the card rejects points outside of the curve during ECDH.", + "The tested points lie on a part of the plane for which some Edwards, Hessian and Huff form addition formulas work."); + } + + @Override + protected void runTests() throws Exception { + Map pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "degenerate"); + List>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); + for (Map.Entry> e : curveList) { + EC_Curve curve = e.getKey(); + List keys = e.getValue(); + + Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); + Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); + Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); + + Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); + + List 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, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten()); + ecdhTests.add(CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve.")); + } + Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with degenerate public points", ecdhTests.toArray(new Test[0])); + + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId(), prepare, ecdh)); + new Command.Cleanup(this.card).send(); + } + } +} diff --git a/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java deleted file mode 100644 index 425fa06..0000000 --- a/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java +++ /dev/null @@ -1,75 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -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.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.*; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardInvalidCurvesSuite extends CardTestSuite { - - public CardInvalidCurvesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "invalid", "The invalid curve suite tests whether the card rejects points outside of the curve during ECDH."); - } - - @Override - protected void runTests() throws Exception { - /* Set original curves (secg/nist/brainpool). Generate local. - * Try ECDH with invalid public keys of increasing order. - */ - Map pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "invalid"); - List>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry> e : curveList) { - EC_Curve curve = e.getKey(); - List keys = e.getValue(); - - 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.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.SUCCESS); - - Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); - - List 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, 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])); - - Random r = new Random(); - byte[] raw = new byte[128]; - byte[] sig = new byte[40]; - r.nextBytes(raw); - r.nextBytes(sig); - - List ecdsaTests = new LinkedList<>(); - for (EC_Key.Public pub : keys) { - Command setCommand = new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()); - Test setTest = CommandTest.expect(setCommand, Result.ExpectedValue.ANY); - Command ecdsaCommand = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.Signature_ALG_ECDSA_SHA, raw, sig); - Test ecdsaTest = CommandTest.expect(ecdsaCommand, Result.ExpectedValue.FAILURE); - ecdsaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by " + pub.getId(), setTest, ecdsaTest)); - } - Test ecdsa = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by invalid public points", ecdsaTests.toArray(new Test[0])); - - Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test ECDH and ECDSA with points on invalid curves.", ecdh, ecdsa); - - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId(), prepare, tests)); - new Command.Cleanup(this.card).send(); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java new file mode 100644 index 0000000..2543027 --- /dev/null +++ b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java @@ -0,0 +1,75 @@ +package cz.crcs.ectester.reader.test; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Curve; +import cz.crcs.ectester.common.ec.EC_Key; +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.data.EC_Store; +import cz.crcs.ectester.reader.CardMngr; +import cz.crcs.ectester.reader.ECTesterReader; +import cz.crcs.ectester.reader.command.Command; + +import java.util.*; + +import static cz.crcs.ectester.common.test.Result.ExpectedValue; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CardInvalidSuite extends CardTestSuite { + + public CardInvalidSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { + super(writer, cfg, cardManager, "invalid", "The invalid curve suite tests whether the card rejects points outside of the curve during ECDH."); + } + + @Override + protected void runTests() throws Exception { + /* Set original curves (secg/nist/brainpool). Generate local. + * Try ECDH with invalid public keys of increasing order. + */ + Map pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "invalid"); + List>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); + for (Map.Entry> e : curveList) { + EC_Curve curve = e.getKey(); + List keys = e.getValue(); + + 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.SUCCESS); + Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.SUCCESS); + + Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); + + List 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, 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])); + + Random r = new Random(); + byte[] raw = new byte[128]; + byte[] sig = new byte[40]; + r.nextBytes(raw); + r.nextBytes(sig); + + List ecdsaTests = new LinkedList<>(); + for (EC_Key.Public pub : keys) { + Command setCommand = new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()); + Test setTest = CommandTest.expect(setCommand, Result.ExpectedValue.ANY); + Command ecdsaCommand = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.Signature_ALG_ECDSA_SHA, raw, sig); + Test ecdsaTest = CommandTest.expect(ecdsaCommand, Result.ExpectedValue.FAILURE); + ecdsaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by " + pub.getId(), setTest, ecdsaTest)); + } + Test ecdsa = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by invalid public points", ecdsaTests.toArray(new Test[0])); + + Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test ECDH and ECDSA with points on invalid curves.", ecdh, ecdsa); + + doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId(), prepare, tests)); + new Command.Cleanup(this.card).send(); + } + } +} diff --git a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java new file mode 100644 index 0000000..d969cf9 --- /dev/null +++ b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java @@ -0,0 +1,54 @@ +package cz.crcs.ectester.reader.test; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Curve; +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.CardUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.reader.CardMngr; +import cz.crcs.ectester.reader.ECTesterReader; +import cz.crcs.ectester.reader.command.Command; + +import java.util.Map; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CardMiscSuite extends CardTestSuite { + + public CardMiscSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { + super(writer, cfg, cardManager, "miscellaneous", "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves and some Barreto-Naehrig curves with small embedding degree and CM discriminant."); + } + + @Override + protected void runTests() throws Exception { + Map ssCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "supersingular"); + Map bnCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "Barreto-Naehrig"); + + testCurves(ssCurves, "supersingular"); + + testCurves(bnCurves, "Barreto-Naehrig"); + } + + private void testCurves(Map curves, String catName) throws Exception { + for (EC_Curve curve : curves.values()) { + Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); + if (!allocateFirst.ok()) { + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocateFirst)); + continue; + } + + Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); + Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.SUCCESS); + Test ka = 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.SUCCESS); + Test sig = CommandTest.expect(new Command.ECDSA(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_FALSE, null), Result.ExpectedValue.SUCCESS); + + doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + " " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, ka, sig)); + new Command.Cleanup(this.card).send(); + } + } +} diff --git a/src/cz/crcs/ectester/reader/test/CardTwistSuite.java b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java new file mode 100644 index 0000000..46da415 --- /dev/null +++ b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java @@ -0,0 +1,69 @@ +package cz.crcs.ectester.reader.test; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Curve; +import cz.crcs.ectester.common.ec.EC_Key; +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.data.EC_Store; +import cz.crcs.ectester.reader.CardMngr; +import cz.crcs.ectester.reader.ECTesterReader; +import cz.crcs.ectester.reader.command.Command; + +import java.util.*; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CardTwistSuite extends CardTestSuite { + public CardTwistSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { + super(writer, cfg, cardManager, "twist", "The twist test suite tests whether the card correctly rejects points on the quadratic twist of the curve during ECDH."); + } + + @Override + protected void runTests() throws Exception { + Map pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "twist"); + List>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); + for (Map.Entry> e : curveList) { + EC_Curve curve = e.getKey(); + List keys = e.getValue(); + + Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); + Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); + Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); + + Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); + + List 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, 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])); + + Random r = new Random(); + byte[] raw = new byte[128]; + byte[] sig = new byte[40]; + r.nextBytes(raw); + r.nextBytes(sig); + + List ecdsaTests = new LinkedList<>(); + for (EC_Key.Public pub : keys) { + Command setCommand = new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()); + Test setTest = CommandTest.expect(setCommand, Result.ExpectedValue.ANY); + Command ecdsaCommand = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.Signature_ALG_ECDSA_SHA, raw, sig); + Test ecdsaTest = CommandTest.expect(ecdsaCommand, Result.ExpectedValue.FAILURE); + ecdsaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by " + pub.getId(), setTest, ecdsaTest)); + } + Test ecdsa = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by public points on twist", ecdsaTests.toArray(new Test[0])); + + Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, ecdh, ecdsa); + + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId(), prepare, tests)); + new Command.Cleanup(this.card).send(); + } + } +} diff --git a/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java b/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java deleted file mode 100644 index ab8e144..0000000 --- a/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java +++ /dev/null @@ -1,69 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -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.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.*; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardTwistTestSuite extends CardTestSuite { - public CardTwistTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "twist", "The twist test suite tests whether the card correctly rejects points on the quadratic twist of the curve during ECDH."); - } - - @Override - protected void runTests() throws Exception { - Map pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "twist"); - List>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry> e : curveList) { - EC_Curve curve = e.getKey(); - List keys = e.getValue(); - - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); - - Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); - - List 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, 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])); - - Random r = new Random(); - byte[] raw = new byte[128]; - byte[] sig = new byte[40]; - r.nextBytes(raw); - r.nextBytes(sig); - - List ecdsaTests = new LinkedList<>(); - for (EC_Key.Public pub : keys) { - Command setCommand = new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()); - Test setTest = CommandTest.expect(setCommand, Result.ExpectedValue.ANY); - Command ecdsaCommand = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.Signature_ALG_ECDSA_SHA, raw, sig); - Test ecdsaTest = CommandTest.expect(ecdsaCommand, Result.ExpectedValue.FAILURE); - ecdsaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by " + pub.getId(), setTest, ecdsaTest)); - } - Test ecdsa = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by public points on twist", ecdsaTests.toArray(new Test[0])); - - Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, ecdh, ecdsa); - - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId(), prepare, tests)); - new Command.Cleanup(this.card).send(); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java deleted file mode 100644 index 8b648b9..0000000 --- a/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java +++ /dev/null @@ -1,203 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Params; -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.CardUtil; -import cz.crcs.ectester.common.util.ECUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import javacard.security.KeyPair; - -import java.math.BigInteger; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardWrongCurvesSuite extends CardTestSuite { - - public CardWrongCurvesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "wrong", "The wrong curve suite tests whether the card rejects domain parameters which are not curves."); - } - - @Override - protected void runTests() throws Exception { - /* Just do the default run on the wrong curves. - * These should generally fail, the curves aren't curves. - */ - Map curves = EC_Store.getInstance().getObjects(EC_Curve.class, "wrong"); - for (Map.Entry e : curves.entrySet()) { - EC_Curve curve = e.getValue(); - List tests = new LinkedList<>(); - Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); - if (!key.ok()) { - doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()), key)); - continue; - } - tests.add(key); - Test set = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.FAILURE)); - Test generate = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.FAILURE)); - Test setup = runTest(CompoundTest.any(ExpectedValue.SUCCESS, "Set wrong curve and generate keypairs.", set, generate)); - tests.add(setup); - - for (byte kaType : EC_Consts.KA_TYPES) { - Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), ExpectedValue.SUCCESS)); - if (allocate.ok()) { - Test ka = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType), ExpectedValue.FAILURE)); - Test kaTest = runTest(CompoundTest.all(ExpectedValue.SUCCESS, "Allocate and perform KA.", allocate, ka)); - tests.add(kaTest); - } - } - doTest(CompoundTest.function((tsts) -> { - for (int i = 0; i < tsts.length; ++i) { - if (i != 1 && !tsts[i].ok()) { - return new Result(Result.Value.FAILURE, "Some tests did not have the expected result."); - } - } - return new Result(Result.Value.SUCCESS, "All tests had the expected result."); - }, "Wrong curve test of " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()), tests.toArray(new Test[0]))); - } - /* - * 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 - */ - Random r = new Random(); - for (short keyLength : EC_Consts.FP_SIZES) { - byte curve = EC_Consts.getCurve(keyLength, KeyPair.ALG_EC_FP); - Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP), ExpectedValue.SUCCESS)); - if (!key.ok()) { - doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + keyLength + "b ALG_EC_FP.", key)); - continue; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_FP, null), ExpectedValue.SUCCESS); - Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set); - - Test prime0 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_FP, EC_Consts.TRANSFORMATION_ZERO), "Set p = 0.", "ECDH with p = 0."); - Test prime1 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_FP, EC_Consts.TRANSFORMATION_ONE), "Set p = 1.", "ECDH with p = 1."); - - short keyHalf = (short) (keyLength / 2); - BigInteger prime = new BigInteger(keyHalf, 50, r); - BigInteger primePow = prime.pow(2); - byte[] primePowBytes = ECUtil.toByteArray(primePow, keyLength); - EC_Params primePowData = new EC_Params(EC_Consts.PARAMETER_FP, new byte[][]{primePowBytes}); - Test primePower = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, primePowData.getParams(), primePowData.flatten()), "Set p = square of a prime.", "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, keyLength); - EC_Params compositeData = new EC_Params(EC_Consts.PARAMETER_FP, new byte[][]{compositeBytes}); - Test composite = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, compositeData.getParams(), compositeData.flatten()), "Set p = product of two primes.", "ECDH with p = q * s."); - - Test wrongPrime = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted prime parameter.", prime0, prime1, primePower, composite); - - Test resetSetup = CompoundTest.all(ExpectedValue.SUCCESS, "Reset keypair.", set.clone()); - - Test randomG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, (short) (EC_Consts.TRANSFORMATION_FULLRANDOM | EC_Consts.TRANSFORMATION_04_MASK)), "Set G = random non-point/point-like.", "ECDH with non-point G."); - Test zeroG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, EC_Consts.TRANSFORMATION_INFINITY), "Set G = inifnity.", "ECDH with G = infinity."); - Test wrongG = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted G parameter.", zeroG, randomG); - - byte[] originalR = new byte[keyLength]; - EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_R, originalR, (short) 0); - BigInteger originalBigR = new BigInteger(1, originalR); - BigInteger nextPrimeR = originalBigR.nextProbablePrime(); - byte[] nextRBytes = ECUtil.toByteArray(nextPrimeR, keyLength); - EC_Params nextRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{nextRBytes}); - Test primeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, nextRData.getParams(), nextRData.flatten()), "Set R = some prime (but [r]G != infinity).", "ECDH with wrong R, prime."); - byte[] nonprimeRBytes = nextRBytes.clone(); - nonprimeRBytes[0] ^= 1; - EC_Params nonprimeWrongRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{nonprimeRBytes}); - Test nonprimeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, nonprimeWrongRData.getParams(), nonprimeWrongRData.flatten()), "Set R = some composite (but [r]G != infinity).", "ECDH with wrong R, composite."); - - Test wrongR = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted R parameter.", primeWrongR, nonprimeWrongR); - - - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(KeyPair.ALG_EC_FP), setup, wrongPrime, resetSetup, wrongG, resetSetup.clone(), wrongR, resetSetup.clone())); - } - - /* - * For binary field: - * - e1, e2 or e3 is larger than m. - * - e1 = e2 = e3 = 0 - */ - for (short keyLength : EC_Consts.F2M_SIZES) { - byte curve = EC_Consts.getCurve(keyLength, KeyPair.ALG_EC_F2M); - Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M), ExpectedValue.SUCCESS)); - if (!key.ok()) { - doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + keyLength + "b ALG_EC_F2M.", key)); - continue; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_F2M, null), ExpectedValue.SUCCESS); - Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set); - - Test coeff0 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_F2M, EC_Consts.TRANSFORMATION_ZERO), "Set e1 = e2 = e3 = 0.", "ECDH with wrong field polynomial: x^" + keyLength); - - short e1 = (short) (2 * keyLength); - short e2 = (short) (3 * keyLength); - short e3 = (short) (4 * keyLength); - byte[][] coeffBytes = new byte[][]{ - ByteUtil.shortToBytes(keyLength), - ByteUtil.shortToBytes(e1), - ByteUtil.shortToBytes(e2), - ByteUtil.shortToBytes(e3)}; - EC_Params coeffParams = new EC_Params(EC_Consts.PARAMETER_F2M, coeffBytes); - Test coeffLarger = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, coeffParams.getParams(), coeffParams.flatten()), "Set e1=" + e1 + ", e2=" + e2 + ", e3=" + e3, "ECDH with wrong field poly, powers larger than " + keyLength); - - Test wrong = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted field polynomial parameter.", coeff0, coeffLarger); - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(KeyPair.ALG_EC_F2M), setup, wrong)); - } - - /* - * TODO: tests for both Fp and F2m: - * - generator not on curve, - * - generator not on proper subgroup of curve(as specified by order/cofactor), - * - wrong order, - * - wrong cofactor. - */ - } - - private Test ecdhTest(Command setupCmd, String prepareDesc, String fullDesc) { - Test setup = CommandTest.expect(setupCmd, ExpectedValue.FAILURE); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.FAILURE); - Test preparePhase = CompoundTest.any(ExpectedValue.SUCCESS, prepareDesc, setup, generate); - Test allocateECDH = CommandTest.expect(new Command.AllocateKeyAgreement(this.card, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ExpectedValue.SUCCESS); - Test ecdh = 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), ExpectedValue.FAILURE); - - - return CompoundTest.function((tests) -> { - if (preparePhase.ok() | !allocateECDH.ok() | ecdh.ok()) { - return new Result(Result.Value.SUCCESS, "All tests had the expected result."); - } else { - return new Result(Result.Value.FAILURE, "Some tests did not have the expected result."); - } - }, (tests) -> { - preparePhase.run(); - if (preparePhase.ok()) { - return; - } - allocateECDH.run(); - if (!allocateECDH.ok()) { - return; - } - ecdh.run(); - },fullDesc, preparePhase, allocateECDH, ecdh); - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardWrongSuite.java b/src/cz/crcs/ectester/reader/test/CardWrongSuite.java new file mode 100644 index 0000000..6c0d5f5 --- /dev/null +++ b/src/cz/crcs/ectester/reader/test/CardWrongSuite.java @@ -0,0 +1,203 @@ +package cz.crcs.ectester.reader.test; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Curve; +import cz.crcs.ectester.common.ec.EC_Params; +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.CardUtil; +import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.reader.CardMngr; +import cz.crcs.ectester.reader.ECTesterReader; +import cz.crcs.ectester.reader.command.Command; +import javacard.security.KeyPair; + +import java.math.BigInteger; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import static cz.crcs.ectester.common.test.Result.ExpectedValue; +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CardWrongSuite extends CardTestSuite { + + public CardWrongSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { + super(writer, cfg, cardManager, "wrong", "The wrong curve suite tests whether the card rejects domain parameters which are not curves."); + } + + @Override + protected void runTests() throws Exception { + /* Just do the default run on the wrong curves. + * These should generally fail, the curves aren't curves. + */ + Map curves = EC_Store.getInstance().getObjects(EC_Curve.class, "wrong"); + for (Map.Entry e : curves.entrySet()) { + EC_Curve curve = e.getValue(); + List tests = new LinkedList<>(); + Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); + if (!key.ok()) { + doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()), key)); + continue; + } + tests.add(key); + Test set = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.FAILURE)); + Test generate = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.FAILURE)); + Test setup = runTest(CompoundTest.any(ExpectedValue.SUCCESS, "Set wrong curve and generate keypairs.", set, generate)); + tests.add(setup); + + for (byte kaType : EC_Consts.KA_TYPES) { + Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), ExpectedValue.SUCCESS)); + if (allocate.ok()) { + Test ka = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType), ExpectedValue.FAILURE)); + Test kaTest = runTest(CompoundTest.all(ExpectedValue.SUCCESS, "Allocate and perform KA.", allocate, ka)); + tests.add(kaTest); + } + } + doTest(CompoundTest.function((tsts) -> { + for (int i = 0; i < tsts.length; ++i) { + if (i != 1 && !tsts[i].ok()) { + return new Result(Result.Value.FAILURE, "Some tests did not have the expected result."); + } + } + return new Result(Result.Value.SUCCESS, "All tests had the expected result."); + }, "Wrong curve test of " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()), tests.toArray(new Test[0]))); + } + /* + * 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 + */ + Random r = new Random(); + for (short keyLength : EC_Consts.FP_SIZES) { + byte curve = EC_Consts.getCurve(keyLength, KeyPair.ALG_EC_FP); + Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP), ExpectedValue.SUCCESS)); + if (!key.ok()) { + doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + keyLength + "b ALG_EC_FP.", key)); + continue; + } + Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_FP, null), ExpectedValue.SUCCESS); + Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set); + + Test prime0 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_FP, EC_Consts.TRANSFORMATION_ZERO), "Set p = 0.", "ECDH with p = 0."); + Test prime1 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_FP, EC_Consts.TRANSFORMATION_ONE), "Set p = 1.", "ECDH with p = 1."); + + short keyHalf = (short) (keyLength / 2); + BigInteger prime = new BigInteger(keyHalf, 50, r); + BigInteger primePow = prime.pow(2); + byte[] primePowBytes = ECUtil.toByteArray(primePow, keyLength); + EC_Params primePowData = new EC_Params(EC_Consts.PARAMETER_FP, new byte[][]{primePowBytes}); + Test primePower = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, primePowData.getParams(), primePowData.flatten()), "Set p = square of a prime.", "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, keyLength); + EC_Params compositeData = new EC_Params(EC_Consts.PARAMETER_FP, new byte[][]{compositeBytes}); + Test composite = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, compositeData.getParams(), compositeData.flatten()), "Set p = product of two primes.", "ECDH with p = q * s."); + + Test wrongPrime = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted prime parameter.", prime0, prime1, primePower, composite); + + Test resetSetup = CompoundTest.all(ExpectedValue.SUCCESS, "Reset keypair.", set.clone()); + + Test randomG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, (short) (EC_Consts.TRANSFORMATION_FULLRANDOM | EC_Consts.TRANSFORMATION_04_MASK)), "Set G = random non-point/point-like.", "ECDH with non-point G."); + Test zeroG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, EC_Consts.TRANSFORMATION_INFINITY), "Set G = inifnity.", "ECDH with G = infinity."); + Test wrongG = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted G parameter.", zeroG, randomG); + + byte[] originalR = new byte[keyLength]; + EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_R, originalR, (short) 0); + BigInteger originalBigR = new BigInteger(1, originalR); + BigInteger nextPrimeR = originalBigR.nextProbablePrime(); + byte[] nextRBytes = ECUtil.toByteArray(nextPrimeR, keyLength); + EC_Params nextRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{nextRBytes}); + Test primeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, nextRData.getParams(), nextRData.flatten()), "Set R = some prime (but [r]G != infinity).", "ECDH with wrong R, prime."); + byte[] nonprimeRBytes = nextRBytes.clone(); + nonprimeRBytes[0] ^= 1; + EC_Params nonprimeWrongRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{nonprimeRBytes}); + Test nonprimeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, nonprimeWrongRData.getParams(), nonprimeWrongRData.flatten()), "Set R = some composite (but [r]G != infinity).", "ECDH with wrong R, composite."); + + Test wrongR = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted R parameter.", primeWrongR, nonprimeWrongR); + + + doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(KeyPair.ALG_EC_FP), setup, wrongPrime, resetSetup, wrongG, resetSetup.clone(), wrongR, resetSetup.clone())); + } + + /* + * For binary field: + * - e1, e2 or e3 is larger than m. + * - e1 = e2 = e3 = 0 + */ + for (short keyLength : EC_Consts.F2M_SIZES) { + byte curve = EC_Consts.getCurve(keyLength, KeyPair.ALG_EC_F2M); + Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M), ExpectedValue.SUCCESS)); + if (!key.ok()) { + doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + keyLength + "b ALG_EC_F2M.", key)); + continue; + } + Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_F2M, null), ExpectedValue.SUCCESS); + Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set); + + Test coeff0 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_F2M, EC_Consts.TRANSFORMATION_ZERO), "Set e1 = e2 = e3 = 0.", "ECDH with wrong field polynomial: x^" + keyLength); + + short e1 = (short) (2 * keyLength); + short e2 = (short) (3 * keyLength); + short e3 = (short) (4 * keyLength); + byte[][] coeffBytes = new byte[][]{ + ByteUtil.shortToBytes(keyLength), + ByteUtil.shortToBytes(e1), + ByteUtil.shortToBytes(e2), + ByteUtil.shortToBytes(e3)}; + EC_Params coeffParams = new EC_Params(EC_Consts.PARAMETER_F2M, coeffBytes); + Test coeffLarger = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, coeffParams.getParams(), coeffParams.flatten()), "Set e1=" + e1 + ", e2=" + e2 + ", e3=" + e3, "ECDH with wrong field poly, powers larger than " + keyLength); + + Test wrong = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted field polynomial parameter.", coeff0, coeffLarger); + doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(KeyPair.ALG_EC_F2M), setup, wrong)); + } + + /* + * TODO: tests for both Fp and F2m: + * - generator not on curve, + * - generator not on proper subgroup of curve(as specified by order/cofactor), + * - wrong order, + * - wrong cofactor. + */ + } + + private Test ecdhTest(Command setupCmd, String prepareDesc, String fullDesc) { + Test setup = CommandTest.expect(setupCmd, ExpectedValue.FAILURE); + Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.FAILURE); + Test preparePhase = CompoundTest.any(ExpectedValue.SUCCESS, prepareDesc, setup, generate); + Test allocateECDH = CommandTest.expect(new Command.AllocateKeyAgreement(this.card, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ExpectedValue.SUCCESS); + Test ecdh = 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), ExpectedValue.FAILURE); + + + return CompoundTest.function((tests) -> { + if (preparePhase.ok() | !allocateECDH.ok() | ecdh.ok()) { + return new Result(Result.Value.SUCCESS, "All tests had the expected result."); + } else { + return new Result(Result.Value.FAILURE, "Some tests did not have the expected result."); + } + }, (tests) -> { + preparePhase.run(); + if (preparePhase.ok()) { + return; + } + allocateECDH.run(); + if (!allocateECDH.ok()) { + return; + } + ecdh.run(); + },fullDesc, preparePhase, allocateECDH, ecdh); + } +} -- cgit v1.3.1 From 664a36218b693e30bb40567b2d06edd3df8defc7 Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 12 Jul 2018 01:13:53 +0200 Subject: Add docs on implementations, curve forms, addition formulas, scalar mult. --- docs/IMPLEMENTATIONS.md | 459 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 docs/IMPLEMENTATIONS.md (limited to 'docs') diff --git a/docs/IMPLEMENTATIONS.md b/docs/IMPLEMENTATIONS.md new file mode 100644 index 0000000..23010c7 --- /dev/null +++ b/docs/IMPLEMENTATIONS.md @@ -0,0 +1,459 @@ +# Implementations + +This document contains information about possible implementation choices and algorithms when implementing elliptic curve cryptography. It is mainly concerned with curve models, coordinate systems, addition formulas and scalar multiplication algorithms. Also, only curves over \( \mathbb{F}_p \) are analyzed. + +--- + +## Curve models + +### Weierstrass (full) + +#### Affine +$$ y^2 + a_1xy + a_3y = x^3 + a_2x^2 + a_4x + a_6 $$ + +#### Projective +$$ Y^2Z + a_1XYZ + a_3YZ^2 = X^3 + a_2X^2Z + a_4XZ^2 + a_6Z^3 $$ + +### Weierstrass (short) + +[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html) + +#### Affine +$$ y^2 = x^3 + a x + b $$ + +#### Projective +$$ Y^2Z = X^3 + aXZ^2 + bZ^3 $$ + +#### Jacobian +$$ Y^2 = X^3 + aXZ^4 + bZ^6 $$ + + toweierstrass weierx = x + toweierstrass weiery = y + a0 = 1 + a1 = 0 + a2 = 0 + a3 = 0 + a4 = a + a6 = b + fromweierstrass x = weierx + fromweierstrass y = weiery + +### Montgomery + +[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-montgom.html) +#### Affine +$$ By^2 = x^3 + Ax^2 + x $$ + + toweierstrass weierx = x + toweierstrass weiery = y + a0 = b + a1 = 0 + a2 = a + a3 = 0 + a4 = 1 + a6 = 0 + fromweierstrass x = weierx + fromweierstrass y = weiery + +### Edwards + +[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-edwards.html) +#### Affine +$$ x^2 + y^2 = c^2 (1 + dx^2y^2) $$ + + toweierstrass u = (c+y)/(c-y) + toweierstrass v = 2 c (c+y)/(x(c-y)) + a0 = 1/(1-d c^4) + a1 = 0 + a2 = 4/(1-d c^4)-2 + a3 = 0 + a4 = 1 + a6 = 0 + fromweierstrass x = 2 c u/v + fromweierstrass y = c(u-1)/(u+1) + +### Twisted Edwards + +[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-twisted.html) +#### Affine +$$ ax^2 + y^2=1 + dx^2y^2 $$ + + toweierstrass u = (1+y)/(1-y) + toweierstrass v = 2 (1+y)/(x(1-y)) + a0 = 1/(a-d) + a1 = 0 + a2 = 4 a/(a-d)-2 + a3 = 0 + a4 = 1 + a6 = 0 + fromweierstrass x = 2 u/v + fromweierstrass y = (u-1)/(u+1) + +### Hessian + +#### Affine +$$ x^3+y^3+1=3dxy $$ + + toweierstrass u = 12(d^3-1)/(d+x+y)-9 d^2 + toweierstrass v = 36(y-x)(d^3-1)/(d+x+y) + a0 = 1 + a1 = 0 + a2 = 0 + a3 = 0 + a4 = -27 d(d^3+8) + a6 = 54(d^6-20 d^3-8) + fromweierstrass x = (36(d^3-1)-v)/(6(u+9 d^2))-d/2 + fromweierstrass y = (v+36(d^3-1))/(6(u+9 d^2))-d/2 + +--- + +## Coordinates + +### Affine + +$$ [x, y] \in \mathbb{K}^2 $$ + +infinity is special cased, sometimes represented as \( [0] \). + +negation: \(-[x, y] = [x, -y] \) + + - To Projective: \( [x, y] \rightarrow (x : y : 1) \) + - To Jacobian: \( [x, y] \rightarrow (x : y : 1) \) + - To Chudnovsky: ? + +### Projective +\begin{align*} +[X, Y, Z] &\in \mathbb{K}^3 \\ +[X_1, Y_1, Z_1] &\sim [X_2, Y_2, Z_2] \\ +\text{if}\ X_1 &= λ X_2, \\ + Y_1 &= λ Y_2, \\ + Z_1 &= λ Z_2 \\ +\text{for some}\ λ &\in \mathbb{K}^* \\ +(X : Y : Z) &= \{(λ X, λ Y, λ Z) | λ \in \mathbb{K}^* \} +\end{align*} + +infinity is \((0 : 1 : 0)\). + + - To Affine: \( (X : Y : Z) \rightarrow [X/Z, Y/Z] \) + - To Jacobian: ? + - To Chudnovsky: ? + +### Jacobian +\begin{align*} +[X, Y, Z] &\in \mathbb{K}^3 \\ +[X_1, Y_1, Z_1] &\sim [X_2, Y_2, Z_2] \\ +\text{if}\ X_1 &= λ^2 X_2, \\ + Y_1 &= λ^3 Y_2, \\ + Z_1 &= λ Z_2 \\ +\text{for some}\ λ &\in \mathbb{K}^* \\ +(X : Y : Z) &= \{(λ^2 X, λ^3 Y, λ Z) | λ \in \mathbb{K}^* \} +\end{align*} + +infinity is \( (1 : 1 : 0) \). + + - To Affine: \( (X : Y : Z) \rightarrow [X/Z^2, Y/Z^3] \) + - To Projective: ? + - To Chudnovsky: \( (X : Y : Z) \rightarrow (X : Y : Z : Z^2 : Z^3) \) + +### Chudnovsky +\begin{align*} +[X, Y, Z, Z^2, Z^3] &\in \mathbb{K}^5 \\ +(X : Y : Z : Z^2 : Z^3 ) &= \{(λ^2 X, λ^3 Y, λ Z, λ^2 Z^2, λ^3 Z^3) | λ \in \mathbb{K}^* \} +\end{align*} + +infinity is \( (1 : 1 : 0 : 0 : 0) \). ? + + - To Affine: \( (X : Y : Z : Z^2 : Z^3) \rightarrow [X/Z^2, Y/Z^3] \) + - To Projective: ? + - To Jacobian: \( (X : Y : Z : Z^2 : Z^3) \rightarrow (X : Y : Z) \) + + +--- + +## Addition formulas + +See EFD[^3]. + +--- + +## Scalar multiplication + +See TAOCP volume 2, section 4.6.3 for introduction to multiplication/exponentiation and addition/multiplication chains.[^5] + +Scalar multiplication on elliptic curves is very similar to usual multiplication/exponentiation in general additive/multiplicative groups, respectively, with some additional structure: + + - \(A + B\) when \(A \ne B\) might be a different operation from \(A + A = [2]A\), and also sometimes takes different time. + - negation \(-A\) is easy/fast. + - \(0\) sometimes has a special representation and thus requires special casing. + - sometimes, there exists a fast operation of \(\phi: E(\mathbb{F}_p) \rightarrow E(\mathbb{F}_p) \) with \( \phi(P) = [k]P \) for some \(k \in \mathbb{K}\) computable using some endomorphism on the curve. + +Some links: + + - [wiki/Addition_chain](https://en.wikipedia.org/wiki/Addition_chain) + - [wiki/Addition-subtraction_chain](https://en.wikipedia.org/wiki/Addition-subtraction_chain) + - [wiki/Exponentiation_by_squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) + - [wiki/Addition-chain_exponentiation](https://en.wikipedia.org/wiki/Addition-chain_exponentiation) + +We define: + + - \( \lambda(k) = \lfloor \log_2 k \rfloor \) , the size of k + - \( k_i \) , the *i*-th bit of *k* + - \( \nu(k) = \vert \{ i \vert 0 \le i \le \lambda(k), k_i = 1\} \vert \) , the number of nonzero bits in *k* + - \( l(k) \) , the length of NAF of *k* + - \( \sigma(k) = \vert \{ i \vert 0 \le i \le l(k), NAF(k)_i \ne 0 \} \vert \) , the number of nonzero values in the NAF of *k* + - \( C_2 \) , the cost of doubling a point + - \( C_+ \) , the cost of point addition + - \( C_{algo}(k) \) , the cost of scalar multiplication by *k* of the algorithm *algo* + - *Addition chain* of *n*, is a sequence of integers: +\( 1 = a_0, a_1, \ldots, a_r = n\), +where \(a_i = a_j + a_k\) for some \( k \le j < i, \forall i \in \{ 1, 2, \ldots, r \} \) + - *Addition-subtraction chain* of *n*, is a sequence of integers: +\( 1 = a_0, a_1, \ldots, a_r = n\), +where \(a_i = \pm a_j \pm a_k\) for some \( k \le j < i, \forall i \in \{ 1, 2, \ldots, r \} \) + +### Double and Add (binary exponentiation) + +Uses binary addition chain. + +Algorithm 3.26 (right-to-left) in GECC[^1] + + INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q). + OUTPUT: [k]P. + 1. Q ← ∞. + 2. For i from t - 1 downto 0 do + 2.1 If k_i = 1 then Q ← Q + P. + 2.2 P ← 2P. + 3. Return(Q). + +Algorithm 3.27 (left-to-right) in GECC[^1] + + INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q). + OUTPUT: [k]P. + 1. Q ← ∞. + 2. For i from t - 1 downto 0 do + 2.1 Q ← 2Q. + 2.2 If k_i = 1 then Q ← Q + P. + 3. Return(Q). + +Cost: \( C_{binexp}(k) = \lambda(k)C_2 + (\nu(k) - k_0)C_+\)[^7] + +### Double and Add Always (binary exponentiation - constant time) + +Uses binary addition chain, but does all the additions/multiplications. + +Cost: \( C_{const\_binexp}(k) = \lambda(k) (C_2 + C_+) \) ? + +### Binary NAF multiplication (signed binary exponentiation) + +**Definition 3.28**[^1] A *non-adjacent form (NAF)* of a positive integer *k* is an expression \( k = \Sigma_{i=0}^{l - 1} k_i 2^i \) where \(k_i \in \{0, ±1\}, k_{l−1} \ne 0\), and no two consecutive digits \( k_i \) are nonzero. The length of the NAF is *l*. + +Algorithm 3.30 Computing the NAF of a positive integer[^1] + + INPUT: A positive integer k. + OUTPUT: NAF(k). + 1. i ← 0. + 2. While k ≥ 1 do + 2.1 If k is odd then: + k_i ← 2 − (k mod 4), k ← k − k_i ; + 2.2 Else: + k_i ← 0. + 2.3 k ← k/2, i ← i + 1. + 3. Return(k_{i−1}, k_{i−2}, . . ., k_1, k_0). + +Algorithm 3.31 Binary NAF multiplication[^1] + + INPUT: Positive integer k, P ∈ E(F_q). + OUTPUT: [k]P. + 1. Use Algorithm 3.30 to compute NAF(k). + 2. Q ← ∞. + 3. For i from l - 1 downto 0 do + 3.1 Q ← 2Q. + 3.2 If k_i = 1 then Q ← Q + P. + 3.3 If k_i = -1 then Q ← Q - P. + 4. Return(Q). + +Can be made constant time. + +Cost: \( C_{bin\_NAF} = l(k)C_2 + \sigma(k)C_+ + \text{NAF computation cost}\) ? + +### Sliding window + +Algorithm 13.6 in HEHCC[^2] + +Algorithm 3.38 in GECC[^1] + + INPUT: Window width w, positive integer k, P ∈ E(F_q). + OUTPUT: [k]P. + 1. Use Algorithm 3.30 to compute NAF(k). + 2. Compute P_i = [i]P for i ∈ {1, 3, . . ., 2(2^w - (-1)^w)/3 - 1}. //precomputation + 3. Q ← ∞, i ← l - 1. + 4. While i ≥ 0 do + 4.1 If k_i = 0 then: + t ← 1, u ← 0. + Else: + find the largest t ≤ w such that u ← (k_i , . . ., k_{i-t+1}) is odd. + 4.3 Q ← [2^t]Q. + 4.4 If u > 0 then: + Q ← Q + P_u. + Else: + if u < 0 then Q ← Q - P_{-u}. + 4.5 i ← i - t. + 5. Return(Q). + +### Window NAF multiplication + +**Definition 3.32**[^1] Let \( w \ge 2 \) be a positive integer. A *width-w NAF* of a positive integer *k* is an expression \( k = \Sigma_{i=0}^{l - 1} k_i 2^i \) where each nonzero coefficient \( k_i \) is odd, \( \vert k_i \vert < 2^{w - 1}, k_{l-1} \ne 0 \), and at most one of any *w* consecutive digits is nonzero. The length of the width-w NAF is *l*. + + +Algorithm 3.35 Computing the width-w NAF of a positive integer[^1] + + INPUT : Window width w, positive integer k. + OUTPUT : NAF-w(k). + 1. i ← 0. + 2. While k ≥ 1 do + 2.1 If k is odd then: + k_i ← k mods 2^w , k ← k − k_i; // k mods 2^w is an integer u, -2^{w-1} ≤ u < 2^{w-1}, u ≡ k mod 2^w + 2.2 Else: + k_i ← 0. + 2.3 k ← k/2, i ← i + 1. + 3. Return(k_{i−1}, k_{i−2}, . . ., k_1, k_0). + +Algorithm 3.36 in GECC[^1] + + INPUT: Window width w, positive integer k, P ∈ E(F_q). + OUTPUT: [k]P. + 1. Use Algorithm 3.35 to compute NAF-w(k). + 2. Compute P_i = [i]P for i ∈ {1, 3, 5, . . ., 2^{w-1} - 1}. //precomputation + 3. Q ← ∞. + 4. For i from l - 1 downto 0 do + 4.1 Q ← 2Q. + 4.2 If k i = 0 then: + If k_i > 0 then Q ← Q + P_{ki} ; + Else Q ← Q - P_{-k_i} . + 5. Return(Q). + +### Fractional window + +[^10] and [^11] + +### Montgomery ladder + +The same name, Montgomery ladder, is used both for the general ladder idea of exponentiation/scalar-multiplication and the concrete *x*-coordinate only addition formulas and scalar multiplication algorithm on Montgomery curves. + +Algorithm 13.35 in [^2] (general Montgomery ladder) + + INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q). + OUTPUT: [k]P . + 1. P_1 ← P and P_2 ← [2]P + 2. For i = t − 2 downto 0 do + 2.1 If k_i = 0 then + P_1 ← [2]P_1; P_2 ← P_1 + P_2. + Else + P_1 ← P_1 + P_2; P_2 ← [2]P_2. + 3. Return(P_1). + +Algorithm 3. in [^8] (general Montgomery ladder) + + INPUT: G ∈ E(F_q), k = (1, k_{t−2}, . . . , k_0)2 + OUTPUT: Y = kG + R0 ← G; R1 ← [2]G + for j = t − 2 downto 0 do + if (k_j = 0) then + R1 ← R0 + R1; R0 ← [2]R0 + else [if (kj = 1)] + R0 ← R0 + R1; R1 ← [2]R1 + return R0 + +Montgomery addition formulas (Projective coordinates/XZ coordinates):[^2] + + - Addition (\( n \ne m \)): +\begin{align*} +X_{m+n} &= Z_{m-n}((X_m - Z_m)(X_n + Z_n) + (X_m + Z_m)(X_n - Z_n))^2 \\ +Z_{m+n} &= X_{m-n}((X_m - Z_m)(X_n + Z_n) - (X_m + Z_m)(X_n - Z_n))^2 +\end{align*} + + - Doubling: +\begin{align*} +4X_nZ_n &= (X_n + Z_n)^2 - (X_n - Z_n)^2 \\ +X_{2n} &= (X_n + Z_n)^2 (X_n - Z_n)^2 \\ +Z_{2n} &= 4X_nZ_n((X_n - Z_n)^2 + ((A + 2)/4)(4X_nZ_n)) +\end{align*} + + - \( Y \) recovery: +\begin{align*} +x_n &= X_n / Z_n; \qquad x_{n+1} = X_{n+1} / Z_{n+1} \\ +y_n &= \frac{(x_1x_n + 1) (x_1 + x_n + 2A) - 2A - (x_1 - x_n)^2x_{n+1}}{2By_1} +\end{align*} + +### Brier-Joye (+ Lopez-Dahab) ladder + +Not really a scalar-multiplication algorithm. Generalization of the stricter Montgomery ladder(the *x*-coordinate only scalar-mult algo and addition formulas on Montgomery curves) to short Weierstrass elliptic curves over fields of \( \text{char}\ \mathbb{K} \ne 2, 3 \) by Brier & Joye. Furthermore the *x*-coordinate only addition formulas were generalized to curves over \( \mathbb{F}_{2^m} \) by Lopez & Dahab. + +Brier-Joye addition formulas (Projective coordinates/XZ coordinates):[^2] + + - Addition (\( n \ne m \)): +\begin{align*} +X_{m+n} &= Z_{m-n}(-4a_6Z_mZ_n(X_mZ_n + X_nZ_m) + (X_mX_n - a_4 Z_mZ_n)^2) \\ +Z_{m+n} &= X_{m-n}(X_mZ_n - X_nZ_m)^2 +\end{align*} + + - Doubling: +\begin{align*} +X_{2n} &= (X_n^2 - a_4Z_n^2)^2 - 8 a_6X_nZ_n^3 \\ +Z_{2n} &= 4Z_n(X_n(X_n^2 + a_4 Z_n^2) + a_6Z_n^3) +\end{align*} + + - \( Y \) recovery: +\begin{align*} +x_n &= X_n / Z_n; \qquad x_{n+1} = X_{n+1} / Z_{n+1} \\ +y_n &= \frac{2a_6 +(x_1x_n + a_4) (x_1 + x_n) - (x_1 - x_n)^2x_{n+1}}{2y_1} +\end{align*} + +Lopez-Dahab addition formulas (Projective coordinates/XZ coordinates):[^2] + + - Addition (\( n \ne m \)): +\begin{align*} +Z_{m+n} &= (X_mZ_n)^2 + (X_nZ_m)^2 \\ +X_{m+n} &= Z_{m+n}X_{m-n} + X_mZ_nX_nZ_m +\end{align*} + + - Doubling: +\begin{align*} +X_{2n} &= X_n^4 + a_6Z_n^4 = (X_n^2 + \sqrt{a_6}Z_n^2)^2 \\ +Z_{2n} &= X_n^2Z_n^2 +\end{align*} + + - \( Y \) recovery: +\begin{align*} +x_n &= X_n / Z_n; \qquad x_{n+1} = X_{n+1} / Z_{n+1} \\ +y_n &= \frac{(x_n + x_1)((x_n + x_1)(x_{n+1} + x_1) + x_1^2 + y_1)}{x_1} + y_1 +\end{align*} + +### Fixed-base windowing (BGMW) + +Algorithm 3.41 and Algorithm 3.42 in GECC[^1] + + +### Fixed-base comb + +Algorithm 3.44 and Algorithm 3.45 in GECC[^1] + +### Möller-1 + +> The method may fail in some cases in that an addition step may turn out to be a point doubling or may involve the point at infinity (which both requires special treatment and is potentially clearly visible through side channels). However, we will show that the probability of this happening is negligible if multipliers are appropriately selected: Randomly chosen e is safe.[^9] + +## References + +[^1]: HANKERSON, Darrel; MENEZES, Alfred J.; VANSTONE, Scott. Guide to Elliptic Curve Cryptography. New York, USA: Springer, 2004. ISBN 9780387218465. Available from DOI: [10.1007/b97644](https://dx.doi.org/10.1007/b97644). +[^2]: COHEN, Henri; FREY, Gerhard; AVANZI, Roberto M.; DOCHE, Christophe; LANGE, +Tanja; NGUYEN, Kim; VERCAUTEREN, Frederik. Handbook of Elliptic and Hyper- +elliptic Curve Cryptography. CRC Press, 2005-07-19. Discrete Mathematics and It’s Applications, no. 34. ISBN 9781584885184. +[^3]: BERNSTEIN, Daniel J.; LANGE, Tanja. Explicit Formulas Database, +[^4]: +[^5]: KNUTH, Donald: The Art of Computer Programming, Volume 2: Seminumerical algorithms +[^6]: GORDON, Daniel M.: A survey of fast exponentiation methods. +[^7]: MORAIN, Francois; OLIVOS, Jorge: Speeding up the computations on an elliptic curve using addition-subtraction chains. +[^8]: JOYE, Marc; YEN, Sung-Ming: The Montgomery Powering Ladder. +[^9]: MOLLER, Bodo: Securing Elliptic Curve Point Multiplication against Side-Channel Attacks. +[^10]: MOLLER, Bodo: Improved Techniques for Fast Exponentiation. +[^11]: MOLLER, Bodo: Fractional Windows Revisited: Improved Signed-Digit Representations for Efficient Exponentiation \ No newline at end of file -- cgit v1.3.1 From b65fbd884350212cee449fb208636eb3ee76cd49 Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 12 Jul 2018 19:45:23 +0200 Subject: Add tests for curve order being a Carmichael pseudoprime. --- docs/IMPLEMENTATIONS.md | 42 ++++++++++++++---- .../ectester/data/composite/carmichael_128.csv | 1 + .../ectester/data/composite/carmichael_192.csv | 1 + .../ectester/data/composite/carmichael_224.csv | 1 + .../ectester/data/composite/carmichael_256.csv | 1 + .../ectester/data/composite/carmichael_384.csv | 1 + .../ectester/data/composite/carmichael_512.csv | 1 + .../ectester/data/composite/carmichael_521.csv | 1 + src/cz/crcs/ectester/data/composite/curves.xml | 50 ++++++++++++++++++++++ .../ectester/reader/test/CardCompositeSuite.java | 5 +++ 10 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 src/cz/crcs/ectester/data/composite/carmichael_128.csv create mode 100644 src/cz/crcs/ectester/data/composite/carmichael_192.csv create mode 100644 src/cz/crcs/ectester/data/composite/carmichael_224.csv create mode 100644 src/cz/crcs/ectester/data/composite/carmichael_256.csv create mode 100644 src/cz/crcs/ectester/data/composite/carmichael_384.csv create mode 100644 src/cz/crcs/ectester/data/composite/carmichael_512.csv create mode 100644 src/cz/crcs/ectester/data/composite/carmichael_521.csv (limited to 'docs') diff --git a/docs/IMPLEMENTATIONS.md b/docs/IMPLEMENTATIONS.md index 23010c7..4a70b7d 100644 --- a/docs/IMPLEMENTATIONS.md +++ b/docs/IMPLEMENTATIONS.md @@ -119,7 +119,7 @@ negation: \(-[x, y] = [x, -y] \) - To Projective: \( [x, y] \rightarrow (x : y : 1) \) - To Jacobian: \( [x, y] \rightarrow (x : y : 1) \) - - To Chudnovsky: ? + - To Chudnovsky: \( [x, y] \rightarrow (x : y : 1 : 1 : 1) \) ### Projective \begin{align*} @@ -134,9 +134,11 @@ negation: \(-[x, y] = [x, -y] \) infinity is \((0 : 1 : 0)\). +negation: \( -(X : Y : Z) = (X : -Y : Z) \) + - To Affine: \( (X : Y : Z) \rightarrow [X/Z, Y/Z] \) - - To Jacobian: ? - - To Chudnovsky: ? + - To Jacobian: \( (X : Y : Z) \rightarrow (X/Z : Y/Z : 1) \) ? + - To Chudnovsky: \( (X : Y : Z) \rightarrow (X/Z : Y/Z : 1 : 1 : 1) \) ? ### Jacobian \begin{align*} @@ -151,8 +153,10 @@ infinity is \((0 : 1 : 0)\). infinity is \( (1 : 1 : 0) \). +negation: \( -(X : Y : Z) = (X : -Y : Z) \) + - To Affine: \( (X : Y : Z) \rightarrow [X/Z^2, Y/Z^3] \) - - To Projective: ? + - To Projective: \( (X : Y : Z) \rightarrow (X/Z^2 : Y/Z^3 : 1) \) ? - To Chudnovsky: \( (X : Y : Z) \rightarrow (X : Y : Z : Z^2 : Z^3) \) ### Chudnovsky @@ -163,8 +167,10 @@ infinity is \( (1 : 1 : 0) \). infinity is \( (1 : 1 : 0 : 0 : 0) \). ? +negation: \( -(X : Y : Z : Z^2 : Z^3) = (X : -Y : Z : Z^2 : Z^3) \) + - To Affine: \( (X : Y : Z : Z^2 : Z^3) \rightarrow [X/Z^2, Y/Z^3] \) - - To Projective: ? + - To Projective: \( (X : Y : Z : Z^2 : Z^3) \rightarrow (X/Z^2 : Y/Z^3 : 1) \) ? - To Jacobian: \( (X : Y : Z : Z^2 : Z^3) \rightarrow (X : Y : Z) \) @@ -241,6 +247,26 @@ Cost: \( C_{binexp}(k) = \lambda(k)C_2 + (\nu(k) - k_0)C_+\)[^7] Uses binary addition chain, but does all the additions/multiplications. +(right-to-left) + + INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q). + OUTPUT: [k]P. + 1. Q ← ∞. + 2. For i from t - 1 downto 0 do + 2.1 If k_i = 1 then Q ← Q + P else Dummy ← Q + P. + 2.2 P ← 2P. + 3. Return(Q). + +(left-to-right) + + INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q). + OUTPUT: [k]P. + 1. Q ← ∞. + 2. For i from t - 1 downto 0 do + 2.1 Q ← 2Q. + 2.2 If k_i = 1 then Q ← Q + P else Dummy ← Q + P. + 3. Return(Q). + Cost: \( C_{const\_binexp}(k) = \lambda(k) (C_2 + C_+) \) ? ### Binary NAF multiplication (signed binary exponentiation) @@ -285,7 +311,7 @@ Cost: \( C_{bin\_NAF} = l(k)C_2 + \sigma(k)C_+ + \text{NAF computation cost}\) ? INPUT: Window width w, positive integer k, P ∈ E(F_q). OUTPUT: [k]P. 1. Use Algorithm 3.30 to compute NAF(k). - 2. Compute P_i = [i]P for i ∈ {1, 3, . . ., 2(2^w - (-1)^w)/3 - 1}. //precomputation + 2. Compute P_i = [i]P for i ∈ {1, 3, . . ., 2(2^w - (-1)^w)/3 - 1}. //precomputation for fixed P 3. Q ← ∞, i ← l - 1. 4. While i ≥ 0 do 4.1 If k_i = 0 then: @@ -323,7 +349,7 @@ Cost: \( C_{bin\_NAF} = l(k)C_2 + \sigma(k)C_+ + \text{NAF computation cost}\) ? INPUT: Window width w, positive integer k, P ∈ E(F_q). OUTPUT: [k]P. 1. Use Algorithm 3.35 to compute NAF-w(k). - 2. Compute P_i = [i]P for i ∈ {1, 3, 5, . . ., 2^{w-1} - 1}. //precomputation + 2. Compute P_i = [i]P for i ∈ {1, 3, 5, . . ., 2^{w-1} - 1}. //precomputation for fixed P 3. Q ← ∞. 4. For i from l - 1 downto 0 do 4.1 Q ← 2Q. @@ -409,7 +435,7 @@ x_n &= X_n / Z_n; \qquad x_{n+1} = X_{n+1} / Z_{n+1} \\ y_n &= \frac{2a_6 +(x_1x_n + a_4) (x_1 + x_n) - (x_1 - x_n)^2x_{n+1}}{2y_1} \end{align*} -Lopez-Dahab addition formulas (Projective coordinates/XZ coordinates):[^2] +Lopez-Dahab addition formulas on \( E(\mathbb{F}_{2^m}) \)(Projective coordinates/XZ coordinates):[^2] - Addition (\( n \ne m \)): \begin{align*} diff --git a/src/cz/crcs/ectester/data/composite/carmichael_128.csv b/src/cz/crcs/ectester/data/composite/carmichael_128.csv new file mode 100644 index 0000000..400abca --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/carmichael_128.csv @@ -0,0 +1 @@ +0x8d4731c77d3462993d75627d4ea254ef,0x7374f7d098c61f64d0dcd328b537e22c,0x3658ca99638dc513932535134f48536b,0x7d5beaa13395695173e3371b7638347a,0x6f1c533a21abb60316bb9529528910c4,0x8d4731c77d346297e54306afea3730a1,0x01 diff --git a/src/cz/crcs/ectester/data/composite/carmichael_192.csv b/src/cz/crcs/ectester/data/composite/carmichael_192.csv new file mode 100644 index 0000000..7c21982 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/carmichael_192.csv @@ -0,0 +1 @@ +0x8b72c1f15aacdcc4c3d881b3e14fa5e07f614ffd25613c95,0x4de73fecdd02978832f2025306474f85af670aa44735bec4,0x55fa4ea6cbf5241ff5c3734bef8db6399fa45ffbf6450f45,0x0236516a5b59cd7871ed1403e820f07d1795483b5c1cc7c7,0x137236f344d2e6e51476662acc70a2247f81d4801b0b9fa4,0x8b72c1f15aacdcc4c3d881b2a6256f87e98d12e5385af0b9,0x01 diff --git a/src/cz/crcs/ectester/data/composite/carmichael_224.csv b/src/cz/crcs/ectester/data/composite/carmichael_224.csv new file mode 100644 index 0000000..d72a30c --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/carmichael_224.csv @@ -0,0 +1 @@ +0x929fe6161bc19ea029efb679c883576d18d69b5b3a3870eaf80d49a3,0x159ef3437e3d7297247f6ad693c1d80f069cb9eb98a0c679668e5ff9,0x6448a16b4ed54d4532e4145cb5fa9a0cd623232d350f706742aeac8c,0x816e1a2510e83da094374558ba2df28976404fcff6c18bfb5eb8cbf9,0x78f245d80d0e1e18e73272fef47911883ae1ab2af985f93f06dbc002,0x929fe6161bc19ea029efb679c881d967bd62678011c1949852a0b119,0x01 diff --git a/src/cz/crcs/ectester/data/composite/carmichael_256.csv b/src/cz/crcs/ectester/data/composite/carmichael_256.csv new file mode 100644 index 0000000..fea4281 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/carmichael_256.csv @@ -0,0 +1 @@ +0x974a679ba3168a019e1f069aac82c999e2612f1957052c56607e8002ef36be53,0x51f15e6797f0a4f0f049b1aedb340118e9584727c5668fe856ad8e2fa111f12d,0x4e7c9daa52715b65db00a3f85ec87bf6a8cc1c312845fc302fc724eb0067d82e,0x6737dcaa9b8198f73599b700e6b3bfda05731528b620f9080799fd6d491be926,0x0f71d01a2ac0f12fe6db25cc420578e9acb729d007580b139cb4897d6421517c,0x974a679ba3168a019e1f069aac82c9986c8ed1c88f1d90e54250abfb0a363941,0x01 diff --git a/src/cz/crcs/ectester/data/composite/carmichael_384.csv b/src/cz/crcs/ectester/data/composite/carmichael_384.csv new file mode 100644 index 0000000..3002514 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/carmichael_384.csv @@ -0,0 +1 @@ +0xa10402c0f3ab3f57b7ddf22e1b7054a8b2a292e3466496d060a5264d9fe29e2fc22347b3b6c21cdf7cba591fd00abd29,0x3dafe0a9c8fb6540cfb52253c08d63742c122062d031f96b0d901d27c9a91d9cefc6d5df27b9f56664860d02b98bc00c,0x3ae6993a790b7e73d67d1cd3a1376c08b9effb7a43211cd169d4e5871bdf096827d953a9f1a98ad11748b22dadf28f07,0x2f2843692b78f89332597df8bec5f5c55767af145ade2c4ad6a4e08fc772c5b7e2bab7d1cb054ebee4367739fe5d5e5c,0x6940f0d9cd2276b4c909e730cdb909a8742a2abee52fe157ca7401d1d825f57145a3cc20522910b28b90cffc38d64e9b,0xa10402c0f3ab3f57b7ddf22e1b7054a8b2a292e3466496d056717d18f11d70554d3bff46c2b156dc594b563cf7ce93d1,0x01 diff --git a/src/cz/crcs/ectester/data/composite/carmichael_512.csv b/src/cz/crcs/ectester/data/composite/carmichael_512.csv new file mode 100644 index 0000000..59d0b03 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/carmichael_512.csv @@ -0,0 +1 @@ +0x9c4dc6f1cd53c38d5af75215620fb6d643257fb1f658d3e5d3b5412dee1bce65b734e62f7a592cda1f6218a11d07f791503e00190b94521255c291e59a069367,0x624745292ab68c1d121cc5f7bda57be0be0fc2461c212494d44f4d522bf797f31c47ba99b44c7145313aebe5bb03893ed11cfc926082e51426cc2b4347746aa5,0x456e5b484249ffa61273c26a91941dd9f1153b4e972df10cfe7c32c64f8aa6ac0f9ec02b63dec7daff1f30eb1a5ac7b641671092f723175f092f13e5f41f1399,0x4348b5167f4f5d7c3d1265d5f08e08db97cd506b9b2e546d94065220597e79291c2c2ece0f6b904a2a8c39f3adc6706724b56dc26804e19e5fefce5a7763d241,0x61bc72b13f6954704e8d219c2d1a20824dc759503f49b8aed3de1acb1761d68a68fbc93064ba12cac87344690be9027e763e3889ae561904c68bc586407018db,0x9c4dc6f1cd53c38d5af75215620fb6d643257fb1f658d3e5d3b5412dee1bce670a65fd73b857d9d8111f52eb305cfc13d96ca09cdc88e257b289d02d3239d259,0x01 diff --git a/src/cz/crcs/ectester/data/composite/carmichael_521.csv b/src/cz/crcs/ectester/data/composite/carmichael_521.csv new file mode 100644 index 0000000..47ec1c3 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/carmichael_521.csv @@ -0,0 +1 @@ +0x011ebb4ebb42f370324a2b937a20c443f110e1e3c40ecb3eb63af873d0c86e7cce05e5416605f1fcfc8296c879bbea344084007bb8fc2c704d85fc4b7fcdc0a4a001,0x00be420c826bac034b4b24ba623a2551510f6663babc95d6741dd68ab05adf6cf2624b1d47fb76c7b0b3edae8c436befe0b5d536525bd662e911529d00c05437e1db,0x0087789843e5da542f34b7c9737db3f6dbaf515788f355b0e2e36d66eb65d1a183a95a88fb9ffa27807961581ed69473046df573baab472fca6a361228bf326fa7f7,0x00457d321b63688cff7ddb0c04fb4bec1b0da6b5af8cac11b9d6fdce431e80d4b48947329078a7c1c5ca9aeb351a2514f89ef8215adaad9af4f581df098fa088aba6,0x00c286d2f1e48e58787c83878624b273db0fa6c3de13e59e326c0f783a40056dd3623688156396986179d5ee97cf9df846ac7a3180a27a23a45cbb400d9553d8a659,0x11ebb4ebb42f370324a2b937a20c443f110e1e3c40ecb3eb63af873d0c86e7cce1752f780ce79d0886704c8603b16dbb491481c1b6682865a9b7f83440515fbe561,0x01 diff --git a/src/cz/crcs/ectester/data/composite/curves.xml b/src/cz/crcs/ectester/data/composite/curves.xml index 8cec330..c0d61c2 100644 --- a/src/cz/crcs/ectester/data/composite/curves.xml +++ b/src/cz/crcs/ectester/data/composite/curves.xml @@ -250,4 +250,54 @@ composite256_rg0.csv |G| divides r(so [r]G = infinity), but r != |G| = 0x743bc7ea193d40db + + + pp/carmichael128 + 128 + prime + carmichael_128.csv + r = Carmichael pseudoprime = 0x2ddbfe0f1f7 * 0x5bb7fc1e3ed * 0x8993fa2d5e3 + + + pp/carmichael192 + 192 + prime + carmichael_192.csv + r = Carmichael pseudoprime = 0x730ea70deea47eeb * 0xe61d4e1bdd48fdd5 * 0x1592bf529cbed7cbf + + + pp/carmichael224 + 224 + prime + carmichael_224.csv + r = Carmichael pseudoprime = 0x2e6e4205e9ea74ebefd * 0x5cdc840bd3d4e9d7df9 * 0x8b4ac611bdbf5ec3cf5 + + + pp/carmichael256 + 256 + prime + carmichael_256.csv + r = Carmichael pseudoprime = 0x129e94800bf86bd2d04ce1 * 0x253d290017f0d7a5a099c1 * 0x37dbbd8023e9437870e6a1 + + + pp/carmichael384 + 384 + prime + carmichael_384.csv + r = Carmichael pseudoprime = 0x78b4fa97e97300a5c46b32fb522cf76f * 0xf169f52fd2e6014b88d665f6a459eedd * 0x16a1eefc7bc5901f14d4198f1f686e64b + + + pp/carmichael512 + 512 + prime + carmichael_512.csv + r = Carmichael pseudoprime = 0x2f6e41969c169b4e97b0a1c46ca4fb3a8f294afaefb * 0x5edc832d382d369d2f614388d949f6751e5295f5df5 * 0x8e4ac4c3d443d1ebc711e54d45eef1afad7be0f0cef + + + pp/carmichael521 + 521 + prime + carmichael_521.csv + r = Carmichael pseudoprime = 0x170ac4fd154250e674f9ac6e0c29a214c6d6553e4f11 * 0x2e1589fa2a84a1cce9f358dc185344298dacaa7c9e21 * 0x45204ef73fc6f2b35eed054a247ce63e5482ffbaed31 + \ No newline at end of file diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java index b80a0e3..c4b3775 100644 --- a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java @@ -77,6 +77,11 @@ public class CardCompositeSuite extends CardTestSuite { List pqCurves = groupList.stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue(); testGroup(pqCurves, null, ExpectedValue.ANY, "", ""); + /* Also test having G or large order being a Carmichael pseudoprime, R = p * q * r, + */ + List ppCurves = groupList.stream().filter((e) -> e.getKey().equals("pp")).findFirst().get().getValue(); + testGroup(ppCurves, "Generator order = Carmichael pseudoprime", ExpectedValue.ANY, "", ""); + /* Also test rg0 curves. */ List rg0Curves = groupList.stream().filter((e) -> e.getKey().equals("rg0")).findFirst().get().getValue(); -- cgit v1.3.1 From a8b0d3ae683b021128c6e92f29e88eb99111021b Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 13 Jul 2018 01:02:19 +0200 Subject: More docs about addition formulas. --- docs/IMPLEMENTATIONS.md | 73 +++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 26 deletions(-) (limited to 'docs') diff --git a/docs/IMPLEMENTATIONS.md b/docs/IMPLEMENTATIONS.md index 4a70b7d..f8f4e96 100644 --- a/docs/IMPLEMENTATIONS.md +++ b/docs/IMPLEMENTATIONS.md @@ -14,19 +14,11 @@ $$ y^2 + a_1xy + a_3y = x^3 + a_2x^2 + a_4x + a_6 $$ #### Projective $$ Y^2Z + a_1XYZ + a_3YZ^2 = X^3 + a_2X^2Z + a_4XZ^2 + a_6Z^3 $$ + ### Weierstrass (short) [EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html) -#### Affine -$$ y^2 = x^3 + a x + b $$ - -#### Projective -$$ Y^2Z = X^3 + aXZ^2 + bZ^3 $$ - -#### Jacobian -$$ Y^2 = X^3 + aXZ^4 + bZ^6 $$ - toweierstrass weierx = x toweierstrass weiery = y a0 = 1 @@ -38,11 +30,19 @@ $$ Y^2 = X^3 + aXZ^4 + bZ^6 $$ fromweierstrass x = weierx fromweierstrass y = weiery +#### Affine +$$ y^2 = x^3 + a x + b $$ + +#### Projective +$$ Y^2Z = X^3 + aXZ^2 + bZ^3 $$ + +#### Jacobian +$$ Y^2 = X^3 + aXZ^4 + bZ^6 $$ + + ### Montgomery [EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-montgom.html) -#### Affine -$$ By^2 = x^3 + Ax^2 + x $$ toweierstrass weierx = x toweierstrass weiery = y @@ -55,11 +55,13 @@ $$ By^2 = x^3 + Ax^2 + x $$ fromweierstrass x = weierx fromweierstrass y = weiery +#### Affine +$$ By^2 = x^3 + Ax^2 + x $$ + + ### Edwards [EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-edwards.html) -#### Affine -$$ x^2 + y^2 = c^2 (1 + dx^2y^2) $$ toweierstrass u = (c+y)/(c-y) toweierstrass v = 2 c (c+y)/(x(c-y)) @@ -72,11 +74,13 @@ $$ x^2 + y^2 = c^2 (1 + dx^2y^2) $$ fromweierstrass x = 2 c u/v fromweierstrass y = c(u-1)/(u+1) +#### Affine +$$ x^2 + y^2 = c^2 (1 + dx^2y^2) $$ + + ### Twisted Edwards [EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-twisted.html) -#### Affine -$$ ax^2 + y^2=1 + dx^2y^2 $$ toweierstrass u = (1+y)/(1-y) toweierstrass v = 2 (1+y)/(x(1-y)) @@ -89,10 +93,13 @@ $$ ax^2 + y^2=1 + dx^2y^2 $$ fromweierstrass x = 2 u/v fromweierstrass y = (u-1)/(u+1) +#### Affine +$$ ax^2 + y^2=1 + dx^2y^2 $$ + + ### Hessian -#### Affine -$$ x^3+y^3+1=3dxy $$ +[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-hessian.html) toweierstrass u = 12(d^3-1)/(d+x+y)-9 d^2 toweierstrass v = 36(y-x)(d^3-1)/(d+x+y) @@ -105,6 +112,13 @@ $$ x^3+y^3+1=3dxy $$ fromweierstrass x = (36(d^3-1)-v)/(6(u+9 d^2))-d/2 fromweierstrass y = (v+36(d^3-1))/(6(u+9 d^2))-d/2 +#### Affine +$$ x^3+y^3+1=3dxy $$ + +#### Projective +$$ X^3 + Y^3 + Z^3 = 3dXYZ $$ + + --- ## Coordinates @@ -113,9 +127,9 @@ $$ x^3+y^3+1=3dxy $$ $$ [x, y] \in \mathbb{K}^2 $$ -infinity is special cased, sometimes represented as \( [0] \). +*(Weierstrass)* infinity is special cased, sometimes represented as \( [0] \). -negation: \(-[x, y] = [x, -y] \) +*(Weierstrass)* negation: \(-[x, y] = [x, -y] \) - To Projective: \( [x, y] \rightarrow (x : y : 1) \) - To Jacobian: \( [x, y] \rightarrow (x : y : 1) \) @@ -132,9 +146,9 @@ negation: \(-[x, y] = [x, -y] \) (X : Y : Z) &= \{(λ X, λ Y, λ Z) | λ \in \mathbb{K}^* \} \end{align*} -infinity is \((0 : 1 : 0)\). +*(Weierstrass)* infinity is \((0 : 1 : 0)\). -negation: \( -(X : Y : Z) = (X : -Y : Z) \) +*(Weierstrass)* negation: \( -(X : Y : Z) = (X : -Y : Z) \) - To Affine: \( (X : Y : Z) \rightarrow [X/Z, Y/Z] \) - To Jacobian: \( (X : Y : Z) \rightarrow (X/Z : Y/Z : 1) \) ? @@ -151,9 +165,9 @@ negation: \( -(X : Y : Z) = (X : -Y : Z) \) (X : Y : Z) &= \{(λ^2 X, λ^3 Y, λ Z) | λ \in \mathbb{K}^* \} \end{align*} -infinity is \( (1 : 1 : 0) \). +*(Weierstrass)* infinity is \( (1 : 1 : 0) \). -negation: \( -(X : Y : Z) = (X : -Y : Z) \) +*(Weierstrass)* negation: \( -(X : Y : Z) = (X : -Y : Z) \) - To Affine: \( (X : Y : Z) \rightarrow [X/Z^2, Y/Z^3] \) - To Projective: \( (X : Y : Z) \rightarrow (X/Z^2 : Y/Z^3 : 1) \) ? @@ -165,9 +179,9 @@ negation: \( -(X : Y : Z) = (X : -Y : Z) \) (X : Y : Z : Z^2 : Z^3 ) &= \{(λ^2 X, λ^3 Y, λ Z, λ^2 Z^2, λ^3 Z^3) | λ \in \mathbb{K}^* \} \end{align*} -infinity is \( (1 : 1 : 0 : 0 : 0) \). ? +*(Weierstrass)* infinity is \( (1 : 1 : 0 : 0 : 0) \). ? -negation: \( -(X : Y : Z : Z^2 : Z^3) = (X : -Y : Z : Z^2 : Z^3) \) +*(Weierstrass)* negation: \( -(X : Y : Z : Z^2 : Z^3) = (X : -Y : Z : Z^2 : Z^3) \) - To Affine: \( (X : Y : Z : Z^2 : Z^3) \rightarrow [X/Z^2, Y/Z^3] \) - To Projective: \( (X : Y : Z : Z^2 : Z^3) \rightarrow (X/Z^2 : Y/Z^3 : 1) \) ? @@ -176,7 +190,14 @@ negation: \( -(X : Y : Z : Z^2 : Z^3) = (X : -Y : Z : Z^2 : Z^3) \) --- -## Addition formulas +## Formulas + + - Addition + - Doubling + - Tripling + - Differential addition + - Differential addition and doubling + - Scaling See EFD[^3]. -- cgit v1.3.1 From bd657e107ed51ccca25047ab2473f231ef58533e Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 13 Jul 2018 22:13:51 +0200 Subject: Add more docs about implementations. --- docs/IMPLEMENTATIONS.md | 73 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 16 deletions(-) (limited to 'docs') diff --git a/docs/IMPLEMENTATIONS.md b/docs/IMPLEMENTATIONS.md index f8f4e96..4d17600 100644 --- a/docs/IMPLEMENTATIONS.md +++ b/docs/IMPLEMENTATIONS.md @@ -237,6 +237,8 @@ where \(a_i = a_j + a_k\) for some \( k \le j < i, \forall i \in \{ 1, 2, \ldots - *Addition-subtraction chain* of *n*, is a sequence of integers: \( 1 = a_0, a_1, \ldots, a_r = n\), where \(a_i = \pm a_j \pm a_k\) for some \( k \le j < i, \forall i \in \{ 1, 2, \ldots, r \} \) + - *Addition sequence* for \( r_1, r_2, \ldots, r_t \) is an addition chain: \( 1 = a_1, a_2, \ldots, a_l \) which contains \( r_1, r_2, \ldots, r_t \). Useful when operating with one element and many powers \( g^{r_1}, g^{r_2}, \ldots \) + - *Vector addition chain* for \(r \in \mathbb{N}^t \) is a sequence of elements \( v_i \) of \( \mathbb{N}^t \) such that \( v_i = e_i \) for \( 1 \le i \le t \) and \( v_i = v_j + v_k \) for \(j \le k < i \). Useful when powering many elements to many powers \( g_1^{r_1}, g_2^{r_2}, \ldots \) ### Double and Add (binary exponentiation) @@ -290,6 +292,7 @@ Uses binary addition chain, but does all the additions/multiplications. Cost: \( C_{const\_binexp}(k) = \lambda(k) (C_2 + C_+) \) ? + ### Binary NAF multiplication (signed binary exponentiation) **Definition 3.28**[^1] A *non-adjacent form (NAF)* of a positive integer *k* is an expression \( k = \Sigma_{i=0}^{l - 1} k_i 2^i \) where \(k_i \in \{0, ±1\}, k_{l−1} \ne 0\), and no two consecutive digits \( k_i \) are nonzero. The length of the NAF is *l*. @@ -305,9 +308,9 @@ Cost: \( C_{const\_binexp}(k) = \lambda(k) (C_2 + C_+) \) ? 2.2 Else: k_i ← 0. 2.3 k ← k/2, i ← i + 1. - 3. Return(k_{i−1}, k_{i−2}, . . ., k_1, k_0). + 3. Return(k_{i−1}, k_{i−2}, ..., k_1, k_0). -Algorithm 3.31 Binary NAF multiplication[^1] +Algorithm 3.31 Binary NAF multiplication (left-to-right)[^1] INPUT: Positive integer k, P ∈ E(F_q). OUTPUT: [k]P. @@ -323,28 +326,63 @@ Can be made constant time. Cost: \( C_{bin\_NAF} = l(k)C_2 + \sigma(k)C_+ + \text{NAF computation cost}\) ? +### \(m\)-ary method + +Like binary double-and-add but uses a different base *m*.[^6] + + INPUT: k = (k_{t-1}, ..., k_1, k_0)_m, P ∈ E(F_q). + OUTPUT: [k]P + 1. Compute P_i = [i]P for i ∈ {1, 2, ..., m - 1}. + 2. Q ← ∞. + 3. For i from l downto 0 do + 3.1 Q ← [m]Q. + 3.2 Q ← Q + P_{k_i}. + 4. Return(Q). + +### \( 2^r \) method + +Like \(m\)-ary method, with \( m = 2^r \), means that `[m]Q` is doable with only doubling.[^6] + ### Sliding window -Algorithm 13.6 in HEHCC[^2] +Algorithm 13.6 Sliding window in HEHCC[^2] + + INPUT: Window width w, k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q). + OUTPUT: [k]P + 1. Compute P_i = [i]P for i ∈ {3, 5, ..., 2^w - 1}. //precomputation for fixed P + 2. Q ← ∞, i ← t - 1. + 3. While i ≥ 0 do + 3.1 If k_i = 0 then: + Q ← [2]Q, i ← i - 1. + 3.2 Else: + 3.2.1 s ← max(i - k + 1, 0). + 3.2.2 While k_s = 0 do + s ← s + 1. + 3.2.3 For h from 1 to i - s + 1 do + Q ← [2]Q. + 3.2.4 u ← (k_i, ..., k_s)_2. + 3.2.5 Q ← P_u. // u is odd. + 3.2.6 i ← s - 1. + 4. Return(Q). -Algorithm 3.38 in GECC[^1] +Algorithm 3.38 Sliding window with NAF(signed sliding window) in GECC[^1] INPUT: Window width w, positive integer k, P ∈ E(F_q). OUTPUT: [k]P. 1. Use Algorithm 3.30 to compute NAF(k). - 2. Compute P_i = [i]P for i ∈ {1, 3, . . ., 2(2^w - (-1)^w)/3 - 1}. //precomputation for fixed P + 2. Compute P_i = [i]P for i ∈ {1, 3, ..., 2(2^w - (-1)^w)/3 - 1}. //precomputation for fixed P 3. Q ← ∞, i ← l - 1. 4. While i ≥ 0 do 4.1 If k_i = 0 then: t ← 1, u ← 0. - Else: - find the largest t ≤ w such that u ← (k_i , . . ., k_{i-t+1}) is odd. + 4.2 Else: + find the largest t ≤ w such that u ← (k_i , ..., k_{i-t+1}) is odd. 4.3 Q ← [2^t]Q. 4.4 If u > 0 then: Q ← Q + P_u. - Else: + 4.5 Else: if u < 0 then Q ← Q - P_{-u}. - 4.5 i ← i - t. + 4.6 i ← i - t. 5. Return(Q). ### Window NAF multiplication @@ -363,20 +401,22 @@ Cost: \( C_{bin\_NAF} = l(k)C_2 + \sigma(k)C_+ + \text{NAF computation cost}\) ? 2.2 Else: k_i ← 0. 2.3 k ← k/2, i ← i + 1. - 3. Return(k_{i−1}, k_{i−2}, . . ., k_1, k_0). + 3. Return(k_{i−1}, k_{i−2}, ..., k_1, k_0). Algorithm 3.36 in GECC[^1] INPUT: Window width w, positive integer k, P ∈ E(F_q). OUTPUT: [k]P. 1. Use Algorithm 3.35 to compute NAF-w(k). - 2. Compute P_i = [i]P for i ∈ {1, 3, 5, . . ., 2^{w-1} - 1}. //precomputation for fixed P + 2. Compute P_i = [i]P for i ∈ {1, 3, 5, ..., 2^{w-1} - 1}. //precomputation for fixed P 3. Q ← ∞. 4. For i from l - 1 downto 0 do 4.1 Q ← 2Q. - 4.2 If k i = 0 then: - If k_i > 0 then Q ← Q + P_{ki} ; - Else Q ← Q - P_{-k_i} . + 4.2 If k_i != 0 then: + If k_i > 0 then: + Q ← Q + P_{k_i} ; + Else: + Q ← Q - P_{-k_i} . 5. Return(Q). ### Fractional window @@ -401,7 +441,7 @@ The same name, Montgomery ladder, is used both for the general ladder idea of ex Algorithm 3. in [^8] (general Montgomery ladder) - INPUT: G ∈ E(F_q), k = (1, k_{t−2}, . . . , k_0)2 + INPUT: G ∈ E(F_q), k = (1, k_{t−2}, ..., k_0)2 OUTPUT: Y = kG R0 ← G; R1 ← [2]G for j = t − 2 downto 0 do @@ -503,4 +543,5 @@ elliptic Curve Cryptography. CRC Press, 2005-07-19. Discrete Mathematics and It [^8]: JOYE, Marc; YEN, Sung-Ming: The Montgomery Powering Ladder. [^9]: MOLLER, Bodo: Securing Elliptic Curve Point Multiplication against Side-Channel Attacks. [^10]: MOLLER, Bodo: Improved Techniques for Fast Exponentiation. -[^11]: MOLLER, Bodo: Fractional Windows Revisited: Improved Signed-Digit Representations for Efficient Exponentiation \ No newline at end of file +[^11]: MOLLER, Bodo: Fractional Windows Revisited: Improved Signed-Digit Representations for Efficient Exponentiation. +[^12]: KOYAMA, Kenji; TSURUOKA, Yukio: Speeding up Elliptic Cryptosystems by Using a Signed Binary Window Method. \ No newline at end of file -- cgit v1.3.1 From 94430f04698c9fe8675b217ca831d980918db97c Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 14 Jul 2018 01:33:44 +0200 Subject: Add information about BouncyCastle and SunEC libraries. --- docs/IMPLEMENTATIONS.md | 7 ++++++- docs/LIBS.md | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/IMPLEMENTATIONS.md b/docs/IMPLEMENTATIONS.md index 4d17600..b4a4ea8 100644 --- a/docs/IMPLEMENTATIONS.md +++ b/docs/IMPLEMENTATIONS.md @@ -516,6 +516,10 @@ x_n &= X_n / Z_n; \qquad x_{n+1} = X_{n+1} / Z_{n+1} \\ y_n &= \frac{(x_n + x_1)((x_n + x_1)(x_{n+1} + x_1) + x_1^2 + y_1)}{x_1} + y_1 \end{align*} +### GLV scalar multiplication + +[^13] + ### Fixed-base windowing (BGMW) Algorithm 3.41 and Algorithm 3.42 in GECC[^1] @@ -544,4 +548,5 @@ elliptic Curve Cryptography. CRC Press, 2005-07-19. Discrete Mathematics and It [^9]: MOLLER, Bodo: Securing Elliptic Curve Point Multiplication against Side-Channel Attacks. [^10]: MOLLER, Bodo: Improved Techniques for Fast Exponentiation. [^11]: MOLLER, Bodo: Fractional Windows Revisited: Improved Signed-Digit Representations for Efficient Exponentiation. -[^12]: KOYAMA, Kenji; TSURUOKA, Yukio: Speeding up Elliptic Cryptosystems by Using a Signed Binary Window Method. \ No newline at end of file +[^12]: KOYAMA, Kenji; TSURUOKA, Yukio: Speeding up Elliptic Cryptosystems by Using a Signed Binary Window Method. +[^13]: GALLANT, Robert P.; LAMBERT, Robert J.; VANSTONE, Scott A.: Faster point multiplication on elliptic curves with efficient endomorphisms. \ No newline at end of file diff --git a/docs/LIBS.md b/docs/LIBS.md index f6d3896..512dee2 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -14,8 +14,46 @@ Popular libraries with at least some ECC support: - [BouncyCastle](https://bouncycastle.org/java.html) - Java + - Works with the short Weierstrass curve model. + - Works with coordinates: + - Affine + - Projective(Homogenous) + - Jacobian + - Jacobian-Chudnovsky + - Jacobian-Modified + - Lambda-Affine? + - Lambda-Projective? + - Skewed? + - Multiple scalar multiplication algorithms implemented and used: + - Double-and-add always (DoubleAddMultiplier) + - Fixed point comb (FixedPointCombMultiplier) + - GLV (Gallant-Lambert-Vanstone) using endomorphisms (GLVMultiplier): Faster point multiplication on elliptic curves with efficient endomorphisms. <-- default, if available + - Binary NAF right-to-left multiplication(mixed coordinates) (MixedNafR2LMultiplier) + - Montgomery ladder (MontgomeryLadderMultiplier) + - Binary NAF right-to-left multiplication (NafR2LMultiplier) + - Binary NAF left-to-right multiplication (NafL2RMultiplier) + - Double-and-add reference implementation (ReferenceMultiplier) + - Window NAF left-to-right multiplication (WNafL2RMultiplier) <-- default + - Window Tau-NAF multiplication (WTauNafMultiplier): Improved Algorithms for Arithmetic on Anomalous Binary Curves + - Zeroless signed digit binary right-to-left multiplication (ZSignedDigitR2LMultiplier) + - Zeroless signed digit binary left-to-right multiplication (ZSignedDigitL2RMultiplier) + - Has custom field and point arithmetic for: + - Curve25519 (transformed into short Weierstrass model) + - SMP2 curves + - SECG curves - [Sun EC](https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunEC) - Java + C + - Uses the short Weierstrass curve model. + - For prime field curves: + - Uses 5-bit window NAF, Uses mixed Modified-Jacobian coordinates + for doubling and Chudnovsky Jacobian coordinates for additions (ecp_jm.c). From: + Brown, Hankerson, Lopez, Menezes: Software Implementation of the NIST Elliptic Curves Over Prime Fields. + - Contains an implementation of scalar multiplication with 4-bit sliding window, using Jacobian coordinates (ecp_jac.c) + - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ecp_aff.c) + - For binary field curves: + - Uses Lopez-Dahab (Montgomery) ladder, XZ coordinates (ec2_mont.c): Fast multiplication on elliptic curves over GF(2^m) without precomputation (Algorithm 2P) + - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ec2_aff.c) + - Has some custom arithmetic for some of the NIST primes. - [Botan](https://botan.randombit.net/) - C++ - Uses blinded(randomized) Montgomery ladder. -- cgit v1.3.1 From 762cc0c58f3e9b23077a3b0f88fe95232d02935d Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 16 Jul 2018 20:04:14 +0200 Subject: Add tests of increasingly larger prime R to better understand behavior of impls. --- docs/LIBS.md | 6 +- .../ectester/common/output/BaseTextTestWriter.java | 1 + src/cz/crcs/ectester/data/composite/curves.xml | 211 +++++++++++++++++++++ .../ectester/data/composite/varying/160/10.csv | 1 + .../ectester/data/composite/varying/160/112.csv | 1 + .../ectester/data/composite/varying/160/12.csv | 1 + .../ectester/data/composite/varying/160/128.csv | 1 + .../ectester/data/composite/varying/160/135.csv | 1 + .../ectester/data/composite/varying/160/14.csv | 1 + .../ectester/data/composite/varying/160/140.csv | 1 + .../ectester/data/composite/varying/160/144.csv | 1 + .../ectester/data/composite/varying/160/146.csv | 1 + .../ectester/data/composite/varying/160/148.csv | 1 + .../ectester/data/composite/varying/160/150.csv | 1 + .../ectester/data/composite/varying/160/152.csv | 1 + .../data/composite/varying/160/152_cofactor.csv | 1 + .../ectester/data/composite/varying/160/16.csv | 1 + .../crcs/ectester/data/composite/varying/160/2.csv | 1 + .../ectester/data/composite/varying/160/20.csv | 1 + .../ectester/data/composite/varying/160/25.csv | 1 + .../crcs/ectester/data/composite/varying/160/3.csv | 1 + .../ectester/data/composite/varying/160/32.csv | 1 + .../crcs/ectester/data/composite/varying/160/4.csv | 1 + .../ectester/data/composite/varying/160/48.csv | 1 + .../crcs/ectester/data/composite/varying/160/5.csv | 1 + .../crcs/ectester/data/composite/varying/160/6.csv | 1 + .../ectester/data/composite/varying/160/64.csv | 1 + .../crcs/ectester/data/composite/varying/160/7.csv | 1 + .../ectester/data/composite/varying/160/70.csv | 1 + .../crcs/ectester/data/composite/varying/160/8.csv | 1 + .../ectester/data/composite/varying/160/80.csv | 1 + .../ectester/data/composite/varying/160/90.csv | 1 + .../ectester/data/composite/varying/160/96.csv | 1 + .../ectester/reader/test/CardCompositeSuite.java | 12 +- 34 files changed, 255 insertions(+), 5 deletions(-) create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/10.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/112.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/12.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/128.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/135.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/14.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/140.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/144.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/146.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/148.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/150.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/152.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/152_cofactor.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/16.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/2.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/20.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/25.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/3.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/32.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/4.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/48.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/5.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/6.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/64.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/7.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/70.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/8.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/80.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/90.csv create mode 100644 src/cz/crcs/ectester/data/composite/varying/160/96.csv (limited to 'docs') diff --git a/docs/LIBS.md b/docs/LIBS.md index 512dee2..903aef4 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -66,4 +66,8 @@ Popular libraries with at least some ECC support: - Uses Jacobian coordinates. - Sliding window scalar multiplication algorithm. - [Crypto++](https://cryptopp.com/) - - C++ \ No newline at end of file + - C++ + - For prime field curves: + - Uses projective coordinates and sliding window scalar multiplication algorithm. + - For binary field curves: + - Uses affine coordinates and sliding window scalar multiplication algorithm. \ No newline at end of file diff --git a/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java b/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java index ea28489..ee55069 100644 --- a/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java +++ b/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java @@ -58,6 +58,7 @@ public abstract class BaseTextTestWriter implements TestWriter { if (prefix.equals("")) { char charLine[] = new char[BASE_WIDTH + 24]; new String(new char[BASE_WIDTH + 24]).replace("\0", "━").getChars(0, charLine.length - 1, charLine, 0); + charLine[0] = '■'; charLine[4] = '┳'; charLine[BASE_WIDTH + 1] = '┳'; charLine[BASE_WIDTH + 13] = '┳'; diff --git a/src/cz/crcs/ectester/data/composite/curves.xml b/src/cz/crcs/ectester/data/composite/curves.xml index c0d61c2..f1af987 100644 --- a/src/cz/crcs/ectester/data/composite/curves.xml +++ b/src/cz/crcs/ectester/data/composite/curves.xml @@ -300,4 +300,215 @@ carmichael_521.csv r = Carmichael pseudoprime = 0x170ac4fd154250e674f9ac6e0c29a214c6d6553e4f11 * 0x2e1589fa2a84a1cce9f358dc185344298dacaa7c9e21 * 0x45204ef73fc6f2b35eed054a247ce63e5482ffbaed31 + + + varying/160/2 + 160 + prime + varying/160/2.csv + r = 2 bit prime + + + varying/160/3 + 160 + prime + varying/160/3.csv + r = 3 bit prime + + + varying/160/4 + 160 + prime + varying/160/4.csv + r = 4 bit prime + + + varying/160/5 + 160 + prime + varying/160/5.csv + r = 5 bit prime + + + varying/160/6 + 160 + prime + varying/160/6.csv + r = 6 bit prime + + + varying/160/7 + 160 + prime + varying/160/7.csv + r = 7 bit prime + + + varying/160/8 + 160 + prime + varying/160/8.csv + r = 8 bit prime + + + varying/160/10 + 160 + prime + varying/160/10.csv + r = 10 bit prime + + + varying/160/12 + 160 + prime + varying/160/12.csv + r = 12 bit prime + + + varying/160/14 + 160 + prime + varying/160/14.csv + r = 14 bit prime + + + varying/160/16 + 160 + prime + varying/160/16.csv + r = 16 bit prime + + + varying/160/20 + 160 + prime + varying/160/20.csv + r = 20 bit prime + + + varying/160/25 + 160 + prime + varying/160/25.csv + r = 25 bit prime + + + varying/160/32 + 160 + prime + varying/160/32.csv + r = 32 bit prime + + + varying/160/48 + 160 + prime + varying/160/48.csv + r = 48 bit prime + + + varying/160/64 + 160 + prime + varying/160/64.csv + r = 64 bit prime + + + varying/160/70 + 160 + prime + varying/160/70.csv + r = 70 bit prime + + + varying/160/80 + 160 + prime + varying/160/80.csv + r = 80 bit prime + + + varying/160/90 + 160 + prime + varying/160/90.csv + r = 90 bit prime + + + varying/160/96 + 160 + prime + varying/160/96.csv + r = 96 bit prime + + + varying/160/112 + 160 + prime + varying/160/112.csv + r = 112 bit prime + + + varying/160/128 + 160 + prime + varying/160/128.csv + r = 128 bit prime + + + varying/160/135 + 160 + prime + varying/160/135.csv + r = 135 bit prime + + + varying/160/140 + 160 + prime + varying/160/140.csv + r = 140 bit prime + + + varying/160/144 + 160 + prime + varying/160/144.csv + r = 144 bit prime + + + varying/160/146 + 160 + prime + varying/160/146.csv + r = 146 bit prime + + + varying/160/148 + 160 + prime + varying/160/148.csv + r = 148 bit prime + + + varying/160/150 + 160 + prime + varying/160/150.csv + r = 150 bit prime + + + varying/160/152 + 160 + prime + varying/160/152.csv + r = 152 bit prime + + + varying/160/152cofactor + 160 + prime + varying/160/152_cofactor.csv + r = 152 bit prime, with correct cofactor + \ No newline at end of file diff --git a/src/cz/crcs/ectester/data/composite/varying/160/10.csv b/src/cz/crcs/ectester/data/composite/varying/160/10.csv new file mode 100644 index 0000000..5fa842a --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/10.csv @@ -0,0 +1 @@ +0xb1c8eb4d314d22f1bdb2294eaed063e64f580611,0x6a1a4b89dc64200e98c46af58e8d7d0a52aba862,0xa0c9a0d9070ceefcaa3f2324668d6e3e9a3bf8f7,0x4b517e44056658e1f778d6c1075eefc644eaae5e,0x15ca498bd6ab9519c5be6f29882cbc68e47479cd,0x0000000000000000000000000000000000000337,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/112.csv b/src/cz/crcs/ectester/data/composite/varying/160/112.csv new file mode 100644 index 0000000..633ccd5 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/112.csv @@ -0,0 +1 @@ +0x9f3386530aa0a8009acbbe9caa919f72c8d5730f,0x33f8b03510268eb1ca33c2996ddacec1b314c5a6,0x4d9b3a2737345fe43069f306eabdc123e8e847b2,0x803f5afafe7ccb0433355eaf7a1aa1e93d1161b0,0x702c66bf3f3235fbcf3e2a7bf3bf56a69169d1c1,0x000000000000c978cb903a08ddcef1daa40de1f5,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/12.csv b/src/cz/crcs/ectester/data/composite/varying/160/12.csv new file mode 100644 index 0000000..62bb1a0 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/12.csv @@ -0,0 +1 @@ +0xa7d15a5258f4f3855cb22ce8d00571133e8ad0f3,0x61f9830a932a4cdd257061624f3b820e9b91db6e,0x758ee90aa5d7fe797c4817d0c2011f062a263429,0x4f448e668102ec49a2042cf2c15f9879d2d14068,0x05043866b8c4d47377f25942b075e835b121ceeb,0x0000000000000000000000000000000000000c25,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/128.csv b/src/cz/crcs/ectester/data/composite/varying/160/128.csv new file mode 100644 index 0000000..5f8c532 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/128.csv @@ -0,0 +1 @@ +0xb13f0d997960752db0a77c95ade4843941645c87,0x7acba0516ea114053bc3e8fa026857990e610d4b,0x7f9755351f5279758bde2b9739c5f907d159ff26,0x08010035ebd4107beb815893817f2b00f7911d96,0x932569a7385306a3b33e4669100feda47db97168,0x00000000c85d322721a790e50860fee459f6292f,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/135.csv b/src/cz/crcs/ectester/data/composite/varying/160/135.csv new file mode 100644 index 0000000..232abff --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/135.csv @@ -0,0 +1 @@ +0xd3f3289b14ab182f38b78fab5dbaf3674c02597d,0xb8880d01c2b44c8a27805524913e438e6458411d,0x89482f3814165014cc30b134849ead387c7ad048,0xc44043b00f6f65000cb63a22fbbb0785985d0699,0x6097e0e529330900f844ccd27a69a96b16509c16,0x0000006c7fcc23ea5ce765d52954b58745d67e81,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/14.csv b/src/cz/crcs/ectester/data/composite/varying/160/14.csv new file mode 100644 index 0000000..c8df53e --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/14.csv @@ -0,0 +1 @@ +0xbdf7ada7a57600f5d5b371b51218a619536cebc7,0x799707863618aaaffb5d46ca3427d6cfecdc6476,0x590f7e7193a997a2b60ab8e31107f1832473290b,0x795684e5a9816c14dff9c8b509c8c87afa3bbbc3,0xaabbea132ba2097d8025a5387aed8482147c530a,0x0000000000000000000000000000000000003437,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/140.csv b/src/cz/crcs/ectester/data/composite/varying/160/140.csv new file mode 100644 index 0000000..4d59858 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/140.csv @@ -0,0 +1 @@ +0xcf8ecac9bc992d2df7ba9015b5bdcbdf2d1c2aa9,0xa067f72ab472977a150f4684df8e9ccee909489f,0x080cac1702258fce0fbafbdb4f861ad4554a05c6,0xa4601066e4fcb7308022ac922a3a1475197e723e,0x0a210871677b6b921846b4ff0c055cd93f2aa275,0x00000fe55175f2c1fc9827ef4997357705b40a5d,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/144.csv b/src/cz/crcs/ectester/data/composite/varying/160/144.csv new file mode 100644 index 0000000..e8c6492 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/144.csv @@ -0,0 +1 @@ +0xc4bfe673203f80fd04c89a5942c18074bcc2a719,0x9d4a0edafeb576559fe95f1dfde0e006a9e0f6fb,0x2c075927ef142a14c84de72b208e8b5ee1d762b0,0x5a808971a0093ceadb15cf76068c5e7c3c4269b1,0x27a0f2741a55767ef3175461120c5f42a5b54f4f,0x0000d9935a273b9b1402519925d6a6a8b4f9342b,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/146.csv b/src/cz/crcs/ectester/data/composite/varying/160/146.csv new file mode 100644 index 0000000..f656c72 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/146.csv @@ -0,0 +1 @@ +0xbdf7ada7a57600f5d5b371b51218a619536cebc7,0x799707863618aaaffb5d46ca3427d6cfecdc6476,0x590f7e7193a997a2b60ab8e31107f1832473290b,0x4ccf365eda5a0e85438b6df2bf57d668cf5d8192,0x702b5f386587f0d85e6cf56b511de035b62c4379,0x0003a3606233edce56cac59bd01e622561e99e77,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/148.csv b/src/cz/crcs/ectester/data/composite/varying/160/148.csv new file mode 100644 index 0000000..b292889 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/148.csv @@ -0,0 +1 @@ +0xa7d15a5258f4f3855cb22ce8d00571133e8ad0f3,0x61f9830a932a4cdd257061624f3b820e9b91db6e,0x758ee90aa5d7fe797c4817d0c2011f062a263429,0x356da5d90cef81adb97a8cc3e95861fc156ab6c3,0x63ea1cb827821f6d3599e303594a4e21911971a3,0x000dd1818cc0197085816a97b6056c3917bb32d9,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/150.csv b/src/cz/crcs/ectester/data/composite/varying/160/150.csv new file mode 100644 index 0000000..c1bf12e --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/150.csv @@ -0,0 +1 @@ +0xb1c8eb4d314d22f1bdb2294eaed063e64f580611,0x6a1a4b89dc64200e98c46af58e8d7d0a52aba862,0xa0c9a0d9070ceefcaa3f2324668d6e3e9a3bf8f7,0x39ce0be4410100e1349fae8ec18fabb91f1816dd,0x3a44dee9ecb21038fb8c3e987e285f09b456bdc7,0x00374d1df48d00aa21837b6f9717173eb656c659,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/152.csv b/src/cz/crcs/ectester/data/composite/varying/160/152.csv new file mode 100644 index 0000000..24a03ba --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/152.csv @@ -0,0 +1 @@ +0xc9d72249375ff1884a80e426e79315f02fb6904f,0x003ce7e6420986df1c87895fe1b83ed86f93cf10,0x7ed71b8a343a6d4da4220123d2b3405d9e4f813f,0x3f30626d74214324e1ee6c97341abe2a9b2bdd07,0x17fb8a3dc06dc7680485871fc3ed4f8e8e662778,0x00e7b588f02d33982511ca6ab8485259bf119a2f,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/152_cofactor.csv b/src/cz/crcs/ectester/data/composite/varying/160/152_cofactor.csv new file mode 100644 index 0000000..7861bbd --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/152_cofactor.csv @@ -0,0 +1 @@ +0xc9d72249375ff1884a80e426e79315f02fb6904f,0x003ce7e6420986df1c87895fe1b83ed86f93cf10,0x7ed71b8a343a6d4da4220123d2b3405d9e4f813f,0x3f30626d74214324e1ee6c97341abe2a9b2bdd07,0x17fb8a3dc06dc7680485871fc3ed4f8e8e662778,0x00e7b588f02d33982511ca6ab8485259bf119a2f,0xdf diff --git a/src/cz/crcs/ectester/data/composite/varying/160/16.csv b/src/cz/crcs/ectester/data/composite/varying/160/16.csv new file mode 100644 index 0000000..fd76ff7 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/16.csv @@ -0,0 +1 @@ +0xc4bfe673203f80fd04c89a5942c18074bcc2a719,0x9d4a0edafeb576559fe95f1dfde0e006a9e0f6fb,0x2c075927ef142a14c84de72b208e8b5ee1d762b0,0x364591432aca4ab7e451866819263e32f57fa052,0x634d15df260f3bb8e92cd0d4940d176e2d97bddc,0x000000000000000000000000000000000000e77f,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/2.csv b/src/cz/crcs/ectester/data/composite/varying/160/2.csv new file mode 100644 index 0000000..670f4bc --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/2.csv @@ -0,0 +1 @@ +0x7b6d7f82beae015788a67ad391bb68ad720ba991,0x6f222dd4f5ec04fdb0202f461d10c3fa1cec6d45,0x2792a26122d154d68bdb523330a06cc252894165,0x50fa49d7061feaeec4f4f4592744d26decd6243a,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000002,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/20.csv b/src/cz/crcs/ectester/data/composite/varying/160/20.csv new file mode 100644 index 0000000..940d10c --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/20.csv @@ -0,0 +1 @@ +0xcf8ecac9bc992d2df7ba9015b5bdcbdf2d1c2aa9,0xa067f72ab472977a150f4684df8e9ccee909489f,0x080cac1702258fce0fbafbdb4f861ad4554a05c6,0x4c4356d56316d6556e7b427a3e1aacd1c1805a8a,0x3d55e3b1904c5e66c75b00710068ffaec4a60ddb,0x00000000000000000000000000000000000d0eb3,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/25.csv b/src/cz/crcs/ectester/data/composite/varying/160/25.csv new file mode 100644 index 0000000..318099b --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/25.csv @@ -0,0 +1 @@ +0xd3f3289b14ab182f38b78fab5dbaf3674c02597d,0xb8880d01c2b44c8a27805524913e438e6458411d,0x89482f3814165014cc30b134849ead387c7ad048,0x593ddf0087b88e469110d12067c86b00bb6f219d,0x968f74b30717f0ca56749382ba5aece4182b35d6,0x0000000000000000000000000000000001f4168b,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/3.csv b/src/cz/crcs/ectester/data/composite/varying/160/3.csv new file mode 100644 index 0000000..18ec491 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/3.csv @@ -0,0 +1 @@ +0xd41869824871ccc03ff87bd99c9a6d2eb7c557bd,0x80b0b37638bd5678af01089dbc13a8674ad96422,0x4c2d8f41681795f138af380c86c98e1d6ee2f3a4,0x6597db8eade96de1d5a546172358d578985e4802,0xa8f85050990cbd2d365b4ef44ead757bfb9af8b5,0x0000000000000000000000000000000000000007,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/32.csv b/src/cz/crcs/ectester/data/composite/varying/160/32.csv new file mode 100644 index 0000000..fddfeee --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/32.csv @@ -0,0 +1 @@ +0xb13f0d997960752db0a77c95ade4843941645c87,0x7acba0516ea114053bc3e8fa026857990e610d4b,0x7f9755351f5279758bde2b9739c5f907d159ff26,0x4ce786a838268215724f1edae0ddec658ef20e6a,0xaeaa4f03aefbbf5fbaeb393ca859d8f27ca56a32,0x00000000000000000000000000000000e2768a75,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/4.csv b/src/cz/crcs/ectester/data/composite/varying/160/4.csv new file mode 100644 index 0000000..a5b9e09 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/4.csv @@ -0,0 +1 @@ +0xb12cff876adc5a923ed34fcd10143de02f8e0369,0x6cb241142b8fb14f45608aec44a325ad195044b5,0xa7cb4cbde8d7792bee9d4856d80df54cdc925b1f,0x07527e2751335207ab0ddb4d5692c7d9219990f5,0x1d1cd5f91fce22653562dd0534ddb861e7005cb6,0x000000000000000000000000000000000000000d,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/48.csv b/src/cz/crcs/ectester/data/composite/varying/160/48.csv new file mode 100644 index 0000000..202a15b --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/48.csv @@ -0,0 +1 @@ +0x9f3386530aa0a8009acbbe9caa919f72c8d5730f,0x33f8b03510268eb1ca33c2996ddacec1b314c5a6,0x4d9b3a2737345fe43069f306eabdc123e8e847b2,0x0f1ca7149bc1933e1e7efdc55c325df7ad4ba562,0x3b689e90dec0b6c85d679d970278d0f9fa30f013,0x0000000000000000000000000000ca49f6d457c1,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/5.csv b/src/cz/crcs/ectester/data/composite/varying/160/5.csv new file mode 100644 index 0000000..5f0597c --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/5.csv @@ -0,0 +1 @@ +0xe13cc8432dad5ed8a4d2893803957c1e109e0c8f,0x7102ce05e08a10ffe665313cece127f5ff590473,0x2dcb47653c268fc7b0f767ae66fcefc98055399c,0x2c4b06f7428dda4532fbea727c7b1f84782e9762,0x4406bb147b080724d2be46eb15327dd350d7307a,0x000000000000000000000000000000000000001f,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/6.csv b/src/cz/crcs/ectester/data/composite/varying/160/6.csv new file mode 100644 index 0000000..9c1528f --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/6.csv @@ -0,0 +1 @@ +0xe9e74933088156a9f60b0f23253fe21ce259d783,0x6a01bdfb7c22fa778456edc767d0f61895561f27,0x27591495bbaf4845cf807f59d3091b0ec830b080,0xb956503ece30bccd9dc08bc76da995e390b2d0ea,0x30ca629aa64506f2b5e6c71fe7dea2c4284d1a2a,0x000000000000000000000000000000000000003d,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/64.csv b/src/cz/crcs/ectester/data/composite/varying/160/64.csv new file mode 100644 index 0000000..94a2709 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/64.csv @@ -0,0 +1 @@ +0xba824697c3ac48fbf53bdc6997a10f2e9e9d24fd,0x00878d8c00cc5b137d7ee7f3defe3ee2d614112e,0x439154313b1e0b63a3cf445a67af1f2f9442238c,0x33e0dfbcd3bdbd0a3d98254c8c706852ac9160ec,0xb0895e2997ef93d8b9500068855afeff515284c3,0x000000000000000000000000ee49fe4c5b77e201,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/7.csv b/src/cz/crcs/ectester/data/composite/varying/160/7.csv new file mode 100644 index 0000000..170b180 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/7.csv @@ -0,0 +1 @@ +0xb7a0a5730514d83583a708acd53a492d970022bd,0x6ee6d2a43a4daf1c0190aaf2384644b59b1c7f11,0x1835fc673409a0265da795eb4d0ad15358b3369a,0x0fee93a779b05c49623527d2a0af78315efbded6,0xb75b77ea3261bf5713cdec1cdd7251dff38232d6,0x0000000000000000000000000000000000000065,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/70.csv b/src/cz/crcs/ectester/data/composite/varying/160/70.csv new file mode 100644 index 0000000..1dbf9c0 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/70.csv @@ -0,0 +1 @@ +0xcc0786de97196a16f433bd40cd1932999867b103,0x7a58470e1615f4676bfc6fc57d71c99285a56919,0xa047dff6287d28be79b09ce6a398b57e8c2a97e9,0x570bda529a23c0a651113cdb5083439d3a6fd30c,0x9d71ecbe74fb180d08a7bdbb77e6aad40d2146b7,0x00000000000000000000003ba788abd620e775e7,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/8.csv b/src/cz/crcs/ectester/data/composite/varying/160/8.csv new file mode 100644 index 0000000..232df05 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/8.csv @@ -0,0 +1 @@ +0xc9d72249375ff1884a80e426e79315f02fb6904f,0x003ce7e6420986df1c87895fe1b83ed86f93cf10,0x7ed71b8a343a6d4da4220123d2b3405d9e4f813f,0x083e1d65a5ebcf6f98f2202ea5bfe021db0ce40e,0x16947d2cf97c654222c015b6ff56b9471f9518a9,0x00000000000000000000000000000000000000df,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/80.csv b/src/cz/crcs/ectester/data/composite/varying/160/80.csv new file mode 100644 index 0000000..da082ef --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/80.csv @@ -0,0 +1 @@ +0xd84ff9bc6df5a2f01d087f4c5e35ae905eb55e13,0xa50dbf4c40d4455f045c249b655b146d5d07a8a3,0xd6aed5bd031f7c3af319cdf03d45ee1b2e5c72ae,0x3a2b110757656c93362455ad480d38207b826d38,0x9cf1881da1e1f10777900f8c18996e8fbd3e470f,0x00000000000000000000e74bbc29baa61aca49d1,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/90.csv b/src/cz/crcs/ectester/data/composite/varying/160/90.csv new file mode 100644 index 0000000..d67e673 --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/90.csv @@ -0,0 +1 @@ +0xcc0786de97196a16f433bd40cd1932999867b103,0x7a58470e1615f4676bfc6fc57d71c99285a56919,0xa047dff6287d28be79b09ce6a398b57e8c2a97e9,0x353f1f34902fb9c28b62c145369afa64b301e48c,0x0fd9c5d52882c2af8b99b5209bd80e44839c2e2e,0x0000000000000000036b917bc29fe57e7df01d13,0x01 diff --git a/src/cz/crcs/ectester/data/composite/varying/160/96.csv b/src/cz/crcs/ectester/data/composite/varying/160/96.csv new file mode 100644 index 0000000..5dd2d5c --- /dev/null +++ b/src/cz/crcs/ectester/data/composite/varying/160/96.csv @@ -0,0 +1 @@ +0xba824697c3ac48fbf53bdc6997a10f2e9e9d24fd,0x00878d8c00cc5b137d7ee7f3defe3ee2d614112e,0x439154313b1e0b63a3cf445a67af1f2f9442238c,0x5fb9809c2f608e2fb788c735d0233b2dd1cbc243,0x4e71dd0a87b3d4ff1689a77829ba527781f21cbd,0x0000000000000000c85f0b3dd7355b3a516de59b,0x01 diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java index c4b3775..5de8608 100644 --- a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java @@ -47,13 +47,12 @@ public class CardCompositeSuite extends CardTestSuite { continue; } tests.add(allocate); + tests.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY)); + tests.add(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.ANY)); for (EC_Key key : curveKeys.getValue()) { - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, 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, 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."); - - tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", " + key.getDesc(), set, generate, ecdh)); + tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", " + key.getDesc(), ecdh)); } doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ".", tests.toArray(new Test[0]))); new Command.Cleanup(this.card).send(); @@ -72,6 +71,11 @@ public class CardCompositeSuite extends CardTestSuite { List smallRCurves = groupList.stream().filter((e) -> e.getKey().equals("small")).findFirst().get().getValue(); testGroup(smallRCurves, "Small generator order", ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a small order generator.", "Card incorrectly does ECDH over a small order generator."); + /* Test increasingly larger prime R, to determine where/if card behavior changes. + */ + List varyingCurves = groupList.stream().filter((e) -> e.getKey().equals("varying")).findFirst().get().getValue(); + testGroup(varyingCurves, null, ExpectedValue.ANY, "", ""); + /* Also test having a G of large but composite order, R = p * q, */ List pqCurves = groupList.stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue(); -- cgit v1.3.1 From ed484c16c74f8d4f1e7c211f9583d2e675abae79 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 18 Jul 2018 15:48:37 +0200 Subject: Test anomalous curves as well in misc test suite. --- docs/LIBS.md | 62 +++++++++++----------- .../crcs/ectester/reader/test/CardMiscSuite.java | 22 ++++---- .../ectester/standalone/libs/NativeECLibrary.java | 3 +- 3 files changed, 45 insertions(+), 42 deletions(-) (limited to 'docs') diff --git a/docs/LIBS.md b/docs/LIBS.md index 903aef4..bfe20cd 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -9,50 +9,50 @@ Popular libraries with at least some ECC support: - [OpenSSL (FIPS mode)](https://www.openssl.org/docs/fipsnotes.html) - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) - [Microsoft .NET crypto](https://docs.microsoft.com/en-us/dotnet/standard/security/cryptography-model) - + # Supported libraries - [BouncyCastle](https://bouncycastle.org/java.html) - Java - Works with the short Weierstrass curve model. - Works with coordinates: - - Affine - - Projective(Homogenous) - - Jacobian - - Jacobian-Chudnovsky - - Jacobian-Modified - - Lambda-Affine? - - Lambda-Projective? - - Skewed? + - Affine + - Projective(Homogenous) + - Jacobian + - Jacobian-Chudnovsky + - Jacobian-Modified + - Lambda-Affine? + - Lambda-Projective? + - Skewed? - Multiple scalar multiplication algorithms implemented and used: - - Double-and-add always (DoubleAddMultiplier) - - Fixed point comb (FixedPointCombMultiplier) - - GLV (Gallant-Lambert-Vanstone) using endomorphisms (GLVMultiplier): Faster point multiplication on elliptic curves with efficient endomorphisms. <-- default, if available - - Binary NAF right-to-left multiplication(mixed coordinates) (MixedNafR2LMultiplier) - - Montgomery ladder (MontgomeryLadderMultiplier) - - Binary NAF right-to-left multiplication (NafR2LMultiplier) - - Binary NAF left-to-right multiplication (NafL2RMultiplier) - - Double-and-add reference implementation (ReferenceMultiplier) - - Window NAF left-to-right multiplication (WNafL2RMultiplier) <-- default - - Window Tau-NAF multiplication (WTauNafMultiplier): Improved Algorithms for Arithmetic on Anomalous Binary Curves - - Zeroless signed digit binary right-to-left multiplication (ZSignedDigitR2LMultiplier) - - Zeroless signed digit binary left-to-right multiplication (ZSignedDigitL2RMultiplier) + - Double-and-add always (DoubleAddMultiplier) + - Fixed point comb (FixedPointCombMultiplier) + - GLV (Gallant-Lambert-Vanstone) using endomorphisms (GLVMultiplier): Faster point multiplication on elliptic curves with efficient endomorphisms. <-- default, if available + - Binary NAF right-to-left multiplication(mixed coordinates) (MixedNafR2LMultiplier) + - Montgomery ladder (MontgomeryLadderMultiplier) + - Binary NAF right-to-left multiplication (NafR2LMultiplier) + - Binary NAF left-to-right multiplication (NafL2RMultiplier) + - Double-and-add reference implementation (ReferenceMultiplier) + - Window NAF left-to-right multiplication (WNafL2RMultiplier) <-- default + - Window Tau-NAF multiplication (WTauNafMultiplier): Improved Algorithms for Arithmetic on Anomalous Binary Curves + - Zeroless signed digit binary right-to-left multiplication (ZSignedDigitR2LMultiplier) + - Zeroless signed digit binary left-to-right multiplication (ZSignedDigitL2RMultiplier) - Has custom field and point arithmetic for: - - Curve25519 (transformed into short Weierstrass model) - - SMP2 curves - - SECG curves + - Curve25519 (transformed into short Weierstrass model) + - SMP2 curves + - SECG curves - [Sun EC](https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunEC) - Java + C - Uses the short Weierstrass curve model. - For prime field curves: - - Uses 5-bit window NAF, Uses mixed Modified-Jacobian coordinates + - Uses 5-bit window NAF, Uses mixed Modified-Jacobian coordinates for doubling and Chudnovsky Jacobian coordinates for additions (ecp_jm.c). From: Brown, Hankerson, Lopez, Menezes: Software Implementation of the NIST Elliptic Curves Over Prime Fields. - - Contains an implementation of scalar multiplication with 4-bit sliding window, using Jacobian coordinates (ecp_jac.c) - - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ecp_aff.c) + - Contains an implementation of scalar multiplication with 4-bit sliding window, using Jacobian coordinates (ecp_jac.c) + - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ecp_aff.c) - For binary field curves: - - Uses Lopez-Dahab (Montgomery) ladder, XZ coordinates (ec2_mont.c): Fast multiplication on elliptic curves over GF(2^m) without precomputation (Algorithm 2P) - - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ec2_aff.c) + - Uses Lopez-Dahab (Montgomery) ladder, XZ coordinates (ec2_mont.c): Fast multiplication on elliptic curves over GF(2^m) without precomputation (Algorithm 2P) + - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ec2_aff.c) - Has some custom arithmetic for some of the NIST primes. - [Botan](https://botan.randombit.net/) - C++ @@ -68,6 +68,6 @@ Popular libraries with at least some ECC support: - [Crypto++](https://cryptopp.com/) - C++ - For prime field curves: - - Uses projective coordinates and sliding window scalar multiplication algorithm. + - Uses projective coordinates and sliding window scalar multiplication algorithm. - For binary field curves: - - Uses affine coordinates and sliding window scalar multiplication algorithm. \ No newline at end of file + - Uses affine coordinates and sliding window scalar multiplication algorithm. \ No newline at end of file diff --git a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java index 5dcf727..487fc6a 100644 --- a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java @@ -21,34 +21,36 @@ import java.util.Map; public class CardMiscSuite extends CardTestSuite { public CardMiscSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "miscellaneous", "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves and some Barreto-Naehrig curves with small embedding degree and CM discriminant."); + super(writer, cfg, cardManager, "miscellaneous", "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves, anomalous curves and some Barreto-Naehrig curves with small embedding degree and CM discriminant."); } @Override protected void runTests() throws Exception { + Map anCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "anomalous"); Map ssCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "supersingular"); Map bnCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "Barreto-Naehrig"); - testCurves(ssCurves, "supersingular"); - - testCurves(bnCurves, "Barreto-Naehrig"); + testCurves(anCurves, "anomalous", Result.ExpectedValue.FAILURE); + testCurves(ssCurves, "supersingular", Result.ExpectedValue.FAILURE); + testCurves(bnCurves, "Barreto-Naehrig", Result.ExpectedValue.ANY); } - private void testCurves(Map curves, String catName) throws Exception { + private void testCurves(Map curves, String catName, Result.ExpectedValue expected) throws Exception { for (EC_Curve curve : curves.values()) { Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); if (!allocateFirst.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocateFirst)); + doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocateFirst)); continue; } Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.SUCCESS); - Test ka = 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.SUCCESS); - Test sig = CommandTest.expect(new Command.ECDSA(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_FALSE, null), Result.ExpectedValue.SUCCESS); + Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.ANY); + Test ka = 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), expected); + Test sig = CommandTest.expect(new Command.ECDSA(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_FALSE, null), expected); + Test perform = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH and ECDSA", ka, sig); Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.SUCCESS); - doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + " " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, ka, sig, cleanup)); + doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + " " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform, cleanup)); } } } diff --git a/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java b/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java index 0a420a1..03a088b 100644 --- a/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java +++ b/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java @@ -110,7 +110,8 @@ public abstract class NativeECLibrary extends ProviderECLibrary { provider = createProvider(); return super.initialize(); - } catch (IOException | UnsatisfiedLinkError ignored) { + } catch (IOException | UnsatisfiedLinkError ex) { + System.err.println(ex.getMessage()); } return false; } -- cgit v1.3.1 From 41e5246ed925eee65d86b8463635ea57e2eb706c Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 18 Jul 2018 23:04:35 +0200 Subject: Elementary support for OpenSSL. --- build-standalone.xml | 5 + docs/LIBS.md | 9 +- .../ectester/reader/output/TextTestWriter.java | 6 +- .../ectester/standalone/ECTesterStandalone.java | 17 +- .../crcs/ectester/standalone/libs/OpensslLib.java | 19 + src/cz/crcs/ectester/standalone/libs/jni/Makefile | 10 +- .../standalone/libs/jni/NativeECPrivateKey.java | 6 + .../standalone/libs/jni/NativeECPublicKey.java | 6 + .../libs/jni/NativeKeyPairGeneratorSpi.java | 18 + .../standalone/libs/jni/NativeProvider.java | 10 + src/cz/crcs/ectester/standalone/libs/jni/botan.cpp | 50 --- .../crcs/ectester/standalone/libs/jni/cryptopp.cpp | 53 --- src/cz/crcs/ectester/standalone/libs/jni/native.h | 125 +++++++ src/cz/crcs/ectester/standalone/libs/jni/openssl.c | 393 +++++++++++++++++++++ .../crcs/ectester/standalone/libs/jni/tomcrypt.c | 1 + .../ectester/standalone/output/TextTestWriter.java | 5 +- 16 files changed, 617 insertions(+), 116 deletions(-) create mode 100644 src/cz/crcs/ectester/standalone/libs/OpensslLib.java create mode 100644 src/cz/crcs/ectester/standalone/libs/jni/openssl.c (limited to 'docs') diff --git a/build-standalone.xml b/build-standalone.xml index 4190300..f1ff001 100644 --- a/build-standalone.xml +++ b/build-standalone.xml @@ -122,6 +122,11 @@ + + + + + diff --git a/docs/LIBS.md b/docs/LIBS.md index bfe20cd..59a183f 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -5,8 +5,8 @@ Popular libraries with at least some ECC support: - [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/) - [mbedTLS](https://tls.mbed.org/) - [Nettle](http://www.lysator.liu.se/~nisse/nettle/) - - [OpenSSL](https://www.openssl.org/) - [OpenSSL (FIPS mode)](https://www.openssl.org/docs/fipsnotes.html) + - BoringSSL - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) - [Microsoft .NET crypto](https://docs.microsoft.com/en-us/dotnet/standard/security/cryptography-model) @@ -54,6 +54,13 @@ Popular libraries with at least some ECC support: - Uses Lopez-Dahab (Montgomery) ladder, XZ coordinates (ec2_mont.c): Fast multiplication on elliptic curves over GF(2^m) without precomputation (Algorithm 2P) - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ec2_aff.c) - Has some custom arithmetic for some of the NIST primes. + - [OpenSSL](https://www.openssl.org/) + - C + - For prime field curves: + - Uses Jacobian coordinates, and Montgomery ladder, also uses wNAF-based interleaving multi-exponentiation method(ec_mult.c): http://www.bmoeller.de/pdf/TI-01-08.multiexp.pdf + - Also uses multiplication with precomputation by wNAF splitting(ec_mult.c) + - For binary field curves: + - Uses Jacobian coordinates, and Lopez-Dahab ladder, also uses wNAF-based interleaving multi-exponentiation method(ec2_smpl.c) - [Botan](https://botan.randombit.net/) - C++ - Uses blinded(randomized) Montgomery ladder. diff --git a/src/cz/crcs/ectester/reader/output/TextTestWriter.java b/src/cz/crcs/ectester/reader/output/TextTestWriter.java index a8e4ce9..ad35012 100644 --- a/src/cz/crcs/ectester/reader/output/TextTestWriter.java +++ b/src/cz/crcs/ectester/reader/output/TextTestWriter.java @@ -43,12 +43,12 @@ public class TextTestWriter extends BaseTextTestWriter { if (suite instanceof CardTestSuite) { CardTestSuite cardSuite = (CardTestSuite) suite; StringBuilder sb = new StringBuilder(); - sb.append("═══ " + Colors.underline("ECTester version:") + " " + ECTesterReader.VERSION + ECTesterReader.GIT_COMMIT).append(System.lineSeparator()); - sb.append("═══ " + Colors.underline("Card ATR:") + " ").append(ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false)).append(System.lineSeparator()); + sb.append("═══ ").append(Colors.underline("ECTester version:")).append(" ").append(ECTesterReader.VERSION).append(ECTesterReader.GIT_COMMIT).append(System.lineSeparator()); + sb.append("═══ ").append(Colors.underline("Card ATR:")).append(" ").append(ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false)).append(System.lineSeparator()); try { CardMngr.CPLC cplc = cardSuite.getCard().getCPLC(); if (!cplc.values().isEmpty()) { - sb.append("═══ " + Colors.underline("Card CPLC data:")).append(System.lineSeparator()); + sb.append("═══ ").append(Colors.underline("Card CPLC data:")).append(System.lineSeparator()); for (Map.Entry entry : cplc.values().entrySet()) { CardMngr.CPLC.Field field = entry.getKey(); byte[] value = entry.getValue(); diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java index c223af6..9df6c61 100644 --- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -66,7 +66,7 @@ import java.util.stream.Collectors; * @version v0.2.0 */ public class ECTesterStandalone { - private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib()}; + private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib()}; private Config cfg; private Options opts = new Options(); @@ -205,6 +205,7 @@ public class ECTesterStandalone { opts.addOption(Option.builder("V").longOpt("version").desc("Print version info.").build()); opts.addOption(Option.builder("h").longOpt("help").desc("Print help.").build()); + opts.addOption(Option.builder("C").longOpt("color").desc("Print stuff with color, requires ANSI terminal.").build()); return optParser.parse(opts, args); } @@ -215,22 +216,22 @@ public class ECTesterStandalone { private void listLibraries() { for (ProviderECLibrary lib : libs) { if (lib.isInitialized() && (cfg.selected == null || lib == cfg.selected)) { - System.out.println("\t- " + lib.name()); + System.out.println("\t- " + Colors.bold(lib.name())); Set kpgs = lib.getKPGs(); if (!kpgs.isEmpty()) { - System.out.println("\t\t- KeyPairGenerators: " + String.join(", ", kpgs.stream().map(KeyPairGeneratorIdent::getName).collect(Collectors.toList()))); + System.out.println(Colors.bold("\t\t- KeyPairGenerators: ") + String.join(", ", kpgs.stream().map(KeyPairGeneratorIdent::getName).collect(Collectors.toList()))); } Set eckas = lib.getKAs(); if (!eckas.isEmpty()) { - System.out.println("\t\t- KeyAgreements: " + String.join(", ", eckas.stream().map(KeyAgreementIdent::getName).collect(Collectors.toList()))); + System.out.println(Colors.bold("\t\t- KeyAgreements: ") + String.join(", ", eckas.stream().map(KeyAgreementIdent::getName).collect(Collectors.toList()))); } Set sigs = lib.getSigs(); if (!sigs.isEmpty()) { - System.out.println("\t\t- Signatures: " + String.join(", ", sigs.stream().map(SignatureIdent::getName).collect(Collectors.toList()))); + System.out.println(Colors.bold("\t\t- Signatures: ") + String.join(", ", sigs.stream().map(SignatureIdent::getName).collect(Collectors.toList()))); } Set curves = lib.getCurves(); if (!curves.isEmpty()) { - System.out.println("\t\t- Curves: " + String.join(", ", curves)); + System.out.println(Colors.bold("\t\t- Curves: ") + String.join(", ", curves)); } System.out.println(); } @@ -540,12 +541,16 @@ public class ECTesterStandalone { public static class Config { private ProviderECLibrary[] libs; public ProviderECLibrary selected = null; + public boolean color = false; public Config(ProviderECLibrary[] libs) { this.libs = libs; } boolean readOptions(TreeCommandLine cli) { + color = cli.hasOption("color"); + Colors.enabled = color; + if (cli.isNext("generate") || cli.isNext("export") || cli.isNext("ecdh") || cli.isNext("ecdsa") || cli.isNext("test")) { if (!cli.hasArg(-1)) { System.err.println("Missing library name argument."); diff --git a/src/cz/crcs/ectester/standalone/libs/OpensslLib.java b/src/cz/crcs/ectester/standalone/libs/OpensslLib.java new file mode 100644 index 0000000..e558336 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/OpensslLib.java @@ -0,0 +1,19 @@ +package cz.crcs.ectester.standalone.libs; + +import java.security.Provider; +import java.util.Set; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class OpensslLib extends NativeECLibrary { + public OpensslLib() { + super("openssl_provider", "crypto"); + } + + @Override + native Provider createProvider(); + + @Override + public native Set getCurves(); +} diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile index 17c1efb..9c3557c 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile @@ -42,7 +42,7 @@ CFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. CXXFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. -all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so +all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so # Common utils c_utils.o: c_utils.c @@ -52,6 +52,14 @@ cpp_utils.o: cpp_utils.cpp $(CXX) $(CXXFLAGS) -c $< +# OpenSSL shim +openssl_provider.so: openssl.o c_utils.o + $(CC) -fPIC -g -shared -o $@ $^ -L. $(shell pkg-config --libs openssl) + +openssl.o: openssl.c + $(CC) $(shel pkg-config --cflags openssl) $(CFLAGS) -c $< + + # Libtomcrypt shim tomcrypt_provider.so: tomcrypt.o c_utils.o $(CC) -fPIC -g -shared -o $@ $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt) diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java index a209fa1..39539df 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java @@ -71,4 +71,10 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { super(keyData, params); } } + + public static class Openssl extends Raw { + public Openssl(byte[] keyData, ECParameterSpec params) { + super(keyData, params); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java index f53cd26..1085083 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java @@ -73,4 +73,10 @@ public abstract class NativeECPublicKey implements ECPublicKey { super(keyData, params); } } + + public static class Openssl extends ANSIX962 { + public Openssl(byte[] keyData, ECParameterSpec params) { + super(keyData, params); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java index a7b1a61..6e441e5 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java @@ -155,4 +155,22 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { super("ECDSA"); } } + + public static class Openssl extends NativeKeyPairGeneratorSpi { + public Openssl() { + initialize(256, new SecureRandom()); + } + + @Override + native boolean keysizeSupported(int keysize); + + @Override + native boolean paramsSupported(AlgorithmParameterSpec params); + + @Override + native KeyPair generate(int keysize, SecureRandom random); + + @Override + native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random); + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java index 593295e..a4967e5 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java @@ -49,4 +49,14 @@ public abstract class NativeProvider extends Provider { @Override native void setup(); } + + public static class Openssl extends NativeProvider { + + public Openssl(String name, double version, String info) { + super(name, version, info); + } + + @Override + native void setup(); + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp index 6a1e6d6..a37cb88 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp +++ b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp @@ -20,11 +20,6 @@ static jclass provider_class; -/* - * Class: cz_crcs_ectester_standalone_libs_BotanLib - * Method: createProvider - * Signature: ()Ljava/security/Provider; - */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider(JNIEnv *env, jobject self) { /* Create the custom provider. */ jclass local_provider_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeProvider$Botan"); @@ -44,11 +39,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createP return env->NewObject(provider_class, init, name, version, info); } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan - * Method: setup - * Signature: ()V - */ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Botan_setup(JNIEnv *env, jobject self){ jmethodID provider_put = env->GetMethodID(provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); @@ -88,11 +78,6 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ init_classes(env, "Botan"); } -/* - * Class: cz_crcs_ectester_standalone_libs_BotanLib - * Method: getCurves - * Signature: ()Ljava/util/Set; - */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self){ jclass set_class = env->FindClass("java/util/TreeSet"); @@ -111,20 +96,10 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurv return result; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan - * Method: keysizeSupported - * Signature: (I)Z - */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported(JNIEnv *env, jobject self, jint keysize){ return JNI_TRUE; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan - * Method: paramsSupported - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z - */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_paramsSupported(JNIEnv *env, jobject self, jobject params){ if (params == NULL) { return JNI_FALSE; @@ -319,11 +294,6 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr return env->NewObject(keypair_class, keypair_init, pubkey, privkey); } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan - * Method: generate - * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; - */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random){ const std::set& curves = Botan::EC_Group::known_named_groups(); for (auto it = curves.begin(); it != curves.end(); ++it) { @@ -339,21 +309,11 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai return NULL; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan - * Method: generate - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; - */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ Botan::EC_Group curve_group = group_from_params(env, params); return generate_from_group(env, self, curve_group); } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Botan_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params){ Botan::EC_Group curve_group = group_from_params(env, params); @@ -420,11 +380,6 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey return result; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan - * Method: sign - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params){ Botan::EC_Group curve_group = group_from_params(env, params); @@ -488,11 +443,6 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig return result; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan - * Method: verify - * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z - */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_verify(JNIEnv *env, jobject self, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params){ Botan::EC_Group curve_group = group_from_params(env, params); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp index e83f808..0ba026f 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp +++ b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp @@ -70,11 +70,6 @@ using CryptoPP::Integer; static jclass provider_class; -/* - * Class: cz_crcs_ectester_standalone_libs_CryptoppLib - * Method: createProvider - * Signature: ()Ljava/security/Provider; - */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider(JNIEnv *env, jobject self) { /* Create the custom provider. */ jclass local_provider_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeProvider$Cryptopp"); @@ -100,11 +95,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_crea return env->NewObject(provider_class, init, name, version, info); } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp - * Method: setup - * Signature: ()V - */ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Cryptopp_setup(JNIEnv *env, jobject self){ jmethodID provider_put = env->GetMethodID(provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); @@ -157,11 +147,6 @@ static std::string oid_to_str(const OID &oid) { return ss.str(); } -/* - * Class: cz_crcs_ectester_standalone_libs_CryptoppLib - * Method: getCurves - * Signature: ()Ljava/util/Set; - */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves(JNIEnv *env, jobject self){ jclass set_class = env->FindClass("java/util/TreeSet"); @@ -180,11 +165,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getC return result; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp - * Method: keysizeSupported - * Signature: (I)Z - */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported(JNIEnv *env, jobject self, jint keysize){ std::vector ecp_oids = get_curve_oids(); for (auto oid = ecp_oids.begin(); oid != ecp_oids.end(); ++oid) { @@ -204,11 +184,6 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa return JNI_FALSE; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp - * Method: paramsSupported - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z - */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_paramsSupported(JNIEnv *env, jobject self, jobject params){ if (params == NULL) { return JNI_FALSE; @@ -546,11 +521,6 @@ template jobject generate_from_group(JNIEnv *env, DL_GroupParameters_ return env->NewObject(keypair_class, keypair_init, pubkey, privkey); } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp - * Method: generate - * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; - */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random){ std::vector ecp_oids = get_curve_oids(); for (auto oid = ecp_oids.begin(); oid != ecp_oids.end(); ++oid) { @@ -572,11 +542,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai return NULL; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp - * Method: generate - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; - */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random) { std::unique_ptr> ecp_group = fp_group_from_params(env, params); if (ecp_group == nullptr) { @@ -588,12 +553,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai return NULL; } - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Cryptopp_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { jsize privkey_length = env->GetArrayLength(privkey); jbyte *privkey_data = env->GetByteArrayElements(privkey, NULL); @@ -663,12 +622,6 @@ jbyteArray sign_message(JNIEnv *env, DL_GroupParameters_EC group, jbyteArray return result; } - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp - * Method: sign - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { jclass cryptopp_sig_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Cryptopp"); jfieldID type_id = env->GetFieldID(cryptopp_sig_class, "type", "Ljava/lang/String;"); @@ -715,7 +668,6 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig return result; } - template jboolean verify_message(JNIEnv *env, DL_GroupParameters_EC group, jbyteArray data, jbyteArray signature, jbyteArray pubkey) { typename EC::Point pkey_point; @@ -739,11 +691,6 @@ jboolean verify_message(JNIEnv *env, DL_GroupParameters_EC group, jbyteArray return result; } -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp - * Method: verify - * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z - */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_verify(JNIEnv *env, jobject self, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params) { jclass cryptopp_sig_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Cryptopp"); jfieldID type_id = env->GetFieldID(cryptopp_sig_class, "type", "Ljava/lang/String;"); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h index 9385a4b..6aacdd3 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -513,3 +513,128 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } #endif #endif +/* Header for class cz_crcs_ectester_standalone_libs_OpensslLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_OpensslLib +#define _Included_cz_crcs_ectester_standalone_libs_OpensslLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_OpensslLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_OpensslLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 1421746759512286392LL +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 4112578634029874840LL +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -4298000515446427739LL +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Openssl_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl + * Method: keysizeSupported + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_keysizeSupported + (JNIEnv *, jobject, jint); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl + * Method: paramsSupported + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_paramsSupported + (JNIEnv *, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl + * Method: generate + * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__ILjava_security_SecureRandom_2 + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl + * Method: generate + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 + (JNIEnv *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c new file mode 100644 index 0000000..ae6a222 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c @@ -0,0 +1,393 @@ +#include "native.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "c_utils.h" + + +static jclass provider_class; + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_createProvider(JNIEnv *env, jobject self) { + /* Create the custom provider. */ + jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Openssl"); + provider_class = (*env)->NewGlobalRef(env, local_provider_class); + + jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V"); + + jstring name = (*env)->NewStringUTF(env, OPENSSL_VERSION_TEXT); + double version = ((double)((OPENSSL_VERSION_NUMBER & 0xff000000L) >> 30)) + ((double)((OPENSSL_VERSION_NUMBER & 0xff0000L) >> 20)); + + return (*env)->NewObject(env, provider_class, init, name, version, name); +} + +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Openssl_setup(JNIEnv *env, jobject self) { + OPENSSL_no_config(); + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); + + jmethodID provider_put = (*env)->GetMethodID(env, provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + + jstring ec = (*env)->NewStringUTF(env, "KeyPairGenerator.EC"); + jstring ec_value = (*env)->NewStringUTF(env, "cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$Openssl"); + (*env)->CallObjectMethod(env, self, provider_put, ec, ec_value); + + init_classes(env, "Openssl"); +} + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves(JNIEnv *env, jobject self) { + jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet"); + + jmethodID hash_set_ctr = (*env)->GetMethodID(env, hash_set_class, "", "()V"); + jmethodID hash_set_add = (*env)->GetMethodID(env, hash_set_class, "add", "(Ljava/lang/Object;)Z"); + + jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr); + + size_t ncurves = EC_get_builtin_curves(NULL, 0); + EC_builtin_curve curves[ncurves]; + EC_get_builtin_curves(curves, ncurves); + + for (size_t i = 0; i < ncurves; ++i) { + jstring curve_name = (*env)->NewStringUTF(env, OBJ_nid2sn(curves[i].nid)); + (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name); + } + + return result; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { + size_t ncurves = EC_get_builtin_curves(NULL, 0); + EC_builtin_curve curves[ncurves]; + EC_get_builtin_curves(curves, ncurves); + + for (size_t i = 0; i < ncurves; ++i) { + EC_GROUP *curve = EC_GROUP_new_by_curve_name(curves[i].nid); + if (EC_GROUP_get_degree(curve) == keysize) { + EC_GROUP_clear_free(curve); + return JNI_TRUE; + } + EC_GROUP_free(curve); + } + return JNI_FALSE; +} + +static jobject bignum_to_biginteger(JNIEnv *env, const BIGNUM *bn) { + jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); + int size = BN_num_bytes(bn); + jbyteArray bytes = (*env)->NewByteArray(env, size); + jbyte *data = (*env)->GetByteArrayElements(env, bytes, NULL); + BN_bn2bin(bn, data); + (*env)->ReleaseByteArrayElements(env, bytes, data, JNI_COMMIT); + jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 0, bytes); + return result; +} + +static BIGNUM *biginteger_to_bignum(JNIEnv *env, jobject bigint) { + jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B"); + + jbyteArray byte_array = (jbyteArray) (*env)->CallObjectMethod(env, bigint, to_byte_array); + jsize byte_length = (*env)->GetArrayLength(env, byte_array); + jbyte *byte_data = (*env)->GetByteArrayElements(env, byte_array, NULL); + BIGNUM *result = BN_bin2bn(byte_data, byte_length, NULL); + (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT); + return result; +} + +static EC_GROUP *create_curve(JNIEnv *env, jobject params) { + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject elliptic_curve = (*env)->CallObjectMethod(env, params, get_curve); + + jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;"); + jobject field = (*env)->CallObjectMethod(env, elliptic_curve, get_field); + + jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I"); + jint bits = (*env)->CallIntMethod(env, field, get_bits); + jint bytes = (bits + 7) / 8; + + jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getA", "()Ljava/math/BigInteger;"); + jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a); + BIGNUM *a_bn = biginteger_to_bignum(env, a); + + jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); + jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b); + BIGNUM *b_bn = biginteger_to_bignum(env, b); + + jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;"); + jobject g = (*env)->CallObjectMethod(env, params, get_g); + + jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;"); + jobject gx = (*env)->CallObjectMethod(env, g, get_x); + BIGNUM *gx_bn = biginteger_to_bignum(env, gx); + + jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;"); + jobject gy = (*env)->CallObjectMethod(env, g, get_y); + BIGNUM *gy_bn = biginteger_to_bignum(env, gy); + + EC_GROUP *result; + EC_POINT *g_point; + + if ((*env)->IsInstanceOf(env, field, fp_field_class)) { + jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;"); + jobject p = (*env)->CallObjectMethod(env, field, get_p); + + BIGNUM *p_bn = biginteger_to_bignum(env, p); + result = EC_GROUP_new_curve_GFp(p_bn, a_bn, b_bn, NULL); + BN_free(p_bn); + + g_point = EC_POINT_new(result); + EC_POINT_set_affine_coordinates_GFp(result, g_point, gx_bn, gy_bn, NULL); + } else if ((*env)->IsInstanceOf(env, field, f2m_field_class)) { + + jmethodID get_reduction_poly = (*env)->GetMethodID(env, f2m_field_class, "getReductionPolynomial", "()Ljava/math/BigInteger;"); + jobject red_poly = (*env)->CallObjectMethod(env, field, get_reduction_poly); + + BIGNUM *p_bn = biginteger_to_bignum(env, red_poly); + result = EC_GROUP_new_curve_GF2m(p_bn, a_bn, b_bn, NULL); + BN_free(p_bn); + + g_point = EC_POINT_new(result); + EC_POINT_set_affine_coordinates_GF2m(result, g_point, gx_bn, gy_bn, NULL); + } else { + return NULL; + } + + BN_free(a_bn); + BN_free(b_bn); + + jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;"); + jobject n = (*env)->CallObjectMethod(env, params, get_n); + BIGNUM *n_bn = biginteger_to_bignum(env, n); + + jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I"); + jint h = (*env)->CallIntMethod(env, params, get_h); + BIGNUM *h_bn = BN_new(); + BN_set_word(h_bn, h); + + EC_GROUP_set_generator(result, g_point, n_bn, h_bn); + + BN_free(gx_bn); + BN_free(gy_bn); + BN_free(n_bn); + BN_free(h_bn); + + return result; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_paramsSupported(JNIEnv *env, jobject self, jobject params){ + if (params == NULL) { + return JNI_FALSE; + } + + if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { + EC_GROUP *curve = create_curve(env, params); + jboolean result = (EC_GROUP_check(curve, NULL) == 1) ? JNI_TRUE : JNI_FALSE; + EC_GROUP_free(curve); + return result; + } else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) { + jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;"); + jstring name = (*env)->CallObjectMethod(env, params, get_name); + const char *utf_name = (*env)->GetStringUTFChars(env, name, NULL); + size_t ncurves = EC_get_builtin_curves(NULL, 0); + EC_builtin_curve curves[ncurves]; + EC_get_builtin_curves(curves, ncurves); + for (size_t i = 0; i < ncurves; ++i) { + if (strcasecmp(utf_name, OBJ_nid2sn(curves[i].nid)) == 0) { + (*env)->ReleaseStringUTFChars(env, name, utf_name); + return JNI_TRUE; + } + } + (*env)->ReleaseStringUTFChars(env, name, utf_name); + return JNI_FALSE; + } else { + return JNI_FALSE; + } +} + +static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) { + int field_type = EC_METHOD_get_field_type(EC_GROUP_method_of(curve)); + BIGNUM *a; + BIGNUM *b; + + BIGNUM *gx; + BIGNUM *gy; + jobject field; + + if (field_type == NID_X9_62_prime_field) { + BIGNUM *p = BN_new(); + a = BN_new(); + b = BN_new(); + EC_GROUP_get_curve_GFp(curve, p, a, b, NULL); + + jobject p_int = bignum_to_biginteger(env, p); + + jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "", "(Ljava/math/BigInteger;)V"); + field = (*env)->NewObject(env, fp_field_class, fp_field_init, p_int); + + BN_free(p); + + gx = BN_new(); + gy = BN_new(); + EC_POINT_get_affine_coordinates_GFp(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL); + + } else if (field_type == NID_X9_62_characteristic_two_field) { + a = BN_new(); + b = BN_new(); + EC_GROUP_get_curve_GF2m(curve, NULL, a, b, NULL); + + int basis_type = EC_GROUP_get_basis_type(curve); + jintArray ks; + jint *ks_data; + if (basis_type == NID_X9_62_tpBasis) { + ks = (*env)->NewIntArray(env, 1); + ks_data = (*env)->GetIntArrayElements(env, ks, NULL); + EC_GROUP_get_trinomial_basis(curve, &ks_data[0]); + } else if (basis_type == NID_X9_62_ppBasis) { + ks = (*env)->NewIntArray(env, 3); + ks_data = (*env)->GetIntArrayElements(env, ks, NULL); + EC_GROUP_get_pentanomial_basis(curve, &ks_data[0], &ks_data[1], &ks_data[2]); + } else { + return NULL; + } + (*env)->ReleaseIntArrayElements(env, ks, ks_data, JNI_COMMIT); + + jint m = EC_GROUP_get_degree(curve); + + jmethodID f2m_field_init = (*env)->GetMethodID(env, f2m_field_class, "", "(I[I)V"); + field = (*env)->NewObject(env, f2m_field_class, f2m_field_init, m, ks); + + gx = BN_new(); + gy = BN_new(); + EC_POINT_get_affine_coordinates_GF2m(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL); + } else { + return NULL; + } + + jobject a_int = bignum_to_biginteger(env, a); + jobject b_int = bignum_to_biginteger(env, b); + + jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + jobject elliptic_curve = (*env)->NewObject(env, elliptic_curve_class, elliptic_curve_init, field, a_int, b_int); + fprintf(stderr, "field: %p, a_int: %p, b_int: %p\n", field, a_int, b_int); + fflush(stderr); + + BN_free(a); + BN_free(b); + + jobject gx_int = bignum_to_biginteger(env, gx); + jobject gy_int = bignum_to_biginteger(env, gy); + + BN_free(gx); + BN_free(gy); + + jmethodID point_init = (*env)->GetMethodID(env, point_class, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int); + + jobject order = bignum_to_biginteger(env, EC_GROUP_get0_order(curve)); + jint cofactor = BN_get_word(EC_GROUP_get0_cofactor(curve)); + + jmethodID ec_parameter_spec_init = (*env)->GetMethodID(env, ec_parameter_spec_class, "", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V"); + return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, order, cofactor); +} + +static jobject generate_from_curve(JNIEnv *env, const EC_GROUP *curve) { + jint keysize = EC_GROUP_get_degree(curve); + unsigned long key_bytes = (keysize + 7) / 8; + + EC_KEY *key = EC_KEY_new(); + EC_KEY_set_group(key, curve); + EC_KEY_generate_key(key); + + jbyteArray priv_bytes = (*env)->NewByteArray(env, key_bytes); + jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); + BN_bn2binpad(EC_KEY_get0_private_key(key), key_priv, key_bytes); + (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, JNI_COMMIT); + + unsigned long key_len = 2*keysize + 1; + jbyteArray pub_bytes = (*env)->NewByteArray(env, key_len); + jbyte *key_pub = (*env)->GetByteArrayElements(env, pub_bytes, NULL); + EC_POINT_point2oct(curve, EC_KEY_get0_public_key(key), POINT_CONVERSION_UNCOMPRESSED, key_pub, key_len, NULL); + (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, JNI_COMMIT); + + EC_KEY_free(key); + + jobject ec_param_spec = create_ec_param_spec(env, curve); + + jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec); + jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([BLjava/security/spec/ECParameterSpec;)V"); + jobject pubkey = (*env)->NewObject(env, pubkey_class, ec_pub_init, pub_bytes, ec_param_spec); + + jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec); + jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([BLjava/security/spec/ECParameterSpec;)V"); + jobject privkey = (*env)->NewObject(env, privkey_class, ec_priv_init, priv_bytes, ec_priv_param_spec); + + jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); +} + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { + size_t ncurves = EC_get_builtin_curves(NULL, 0); + EC_builtin_curve curves[ncurves]; + EC_get_builtin_curves(curves, ncurves); + + EC_GROUP *curve = NULL; + for (size_t i = 0; i < ncurves; ++i) { + curve = EC_GROUP_new_by_curve_name(curves[i].nid); + if (EC_GROUP_get_degree(curve) == keysize) { + break; + } + EC_GROUP_free(curve); + } + + if (!curve) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve for given bitsize not found."); + return NULL; + } + + jobject result = generate_from_curve(env, curve); + EC_GROUP_free(curve); + return result; +} + + + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random) { + if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { + EC_GROUP *curve = create_curve(env, params); + jobject result = generate_from_curve(env, curve); + EC_GROUP_free(curve); + return result; + } else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) { + jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;"); + jstring name = (*env)->CallObjectMethod(env, params, get_name); + const char* utf_name = (*env)->GetStringUTFChars(env, name, NULL); + size_t ncurves = EC_get_builtin_curves(NULL, 0); + EC_builtin_curve curves[ncurves]; + EC_get_builtin_curves(curves, ncurves); + EC_GROUP *curve; + for (size_t i = 0; i < ncurves; ++i) { + if (strcasecmp(utf_name, OBJ_nid2sn(curves[i].nid)) == 0) { + curve = EC_GROUP_new_by_curve_name(curves[i].nid); + break; + } + } + (*env)->ReleaseStringUTFChars(env, name, utf_name); + if (!curve) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve for given bitsize not found."); + return NULL; + } + jobject result = generate_from_curve(env, curve); + EC_GROUP_free(curve); + return result; + } else { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); + return NULL; + } +} \ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c index 29ee707..dc3abd9 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c @@ -128,6 +128,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa } curve++; } + (*env)->ReleaseStringUTFChars(env, name, utf_name); return JNI_FALSE; } else { return JNI_FALSE; diff --git a/src/cz/crcs/ectester/standalone/output/TextTestWriter.java b/src/cz/crcs/ectester/standalone/output/TextTestWriter.java index 2e29b07..93be3a8 100644 --- a/src/cz/crcs/ectester/standalone/output/TextTestWriter.java +++ b/src/cz/crcs/ectester/standalone/output/TextTestWriter.java @@ -1,5 +1,6 @@ package cz.crcs.ectester.standalone.output; +import cz.crcs.ectester.common.cli.Colors; import cz.crcs.ectester.common.output.BaseTextTestWriter; import cz.crcs.ectester.common.test.TestSuite; import cz.crcs.ectester.common.test.Testable; @@ -45,8 +46,8 @@ public class TextTestWriter extends BaseTextTestWriter { if (suite instanceof StandaloneTestSuite) { StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite; StringBuilder sb = new StringBuilder(); - sb.append("═══ ECTester version: " + ECTesterStandalone.VERSION).append(System.lineSeparator()); - sb.append("═══ ").append(standaloneSuite.getLibrary().name()).append(System.lineSeparator()); + sb.append("═══ ").append(Colors.underline("ECTester version:")).append(" ").append(ECTesterStandalone.VERSION).append(System.lineSeparator()); + sb.append("═══ ").append(Colors.underline("Library:")).append(standaloneSuite.getLibrary().name()).append(System.lineSeparator()); return sb.toString(); } return ""; -- cgit v1.3.1 From 80ec2bcb69d62267e97f1801f21aed5fe46f109f Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 23 Jul 2018 18:53:35 +0200 Subject: Update docs on TESTS. --- README.md | 5 +++++ docs/TESTS.md | 22 +++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index 1bcef72..daabdd9 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,9 @@ See `java -jar ECTesterReader.jar -h` for more. text,yml,xml. -f,--fresh Generate fresh keys (set domain parameters before every generation). + --cleanup Send the cleanup command trigerring + JCSystem.requestObjectDeletion() + after some operations. -s,--simulate Simulate a card with jcardsim instead of using a terminal. -y,--yes Accept all warnings and prompts. @@ -218,6 +221,8 @@ If you are interested in testing support for other JavaCard algorithms, please v Currently supported libraries include: - BouncyCastle - SunEC + - OpenSSL + - Crypto++ - libtomcrypt - botan diff --git a/docs/TESTS.md b/docs/TESTS.md index 4d71ea6..5811577 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -66,10 +66,16 @@ This test suite also does some additional tests with corrupting the parameters: - p = 1 - p = q^2; q prime - p = q * s; q and s prime - - G = infinity - G = random point not on curve - - r = some prime (and \[r\]G != infinity) + - G = random data + - G = infinity + - r = 0 + - r = 1 + - r = some prime larger than original r (and \[r\]G != infinity) + - r = some prime smaller than original r (and \[r\]G != infninity) - r = some composite number (and \[r\]G != infinity) + - k = 0xff + - k = 0 - F2m: - e1 = e2 = e3 = 0 - m < e1 < e2 < e3 @@ -88,7 +94,10 @@ Tests using curves that don't have a prime order/nearly prime order. These tests should generally fail, a success here implies the card will use a non-secure curve if such curve is set by the applet. Operations over such curves are susceptible to small-subgroup attacks. - - r = p * q + - r = quite a smooth number, many small factors, r = |G| + - r = small prime(of increasing bit lengths), r = |G| + - r = p * q = |G| + - r = G = Carmichael number = p * q * s - \[r\]G = infinity but r != |G|, so |G| divides r For example: @@ -147,12 +156,19 @@ java -jar ECTester.jar -t cofactor ## Edge-Cases Tests various inputs to ECDH which may cause an implementation to achieve a certain edge-case state during ECDH. Some of the data is from the google/Wycheproof project. Tests include [CVE-2017-10176](https://nvd.nist.gov/vuln/detail/CVE-2017-10176) and [CVE-2017-8932](https://nvd.nist.gov/vuln/detail/CVE-2017-8932). +Various custom edge private key values are also tested. CVE-2017-10176 was in implementation issue in the SunEC Java library that caused the implementation to reach the point at infinity during ECDH computation. CVE-2017-8932 was an implementation issue in the Go standard library, in particular its scalar multiplication algorithm on the P-256 curve which leaked information about the private key. +Custom private key values over SECG curves are tested: + - s = 0, s = 1 + - s < r, s = r, s > r + - s = r - 1, s = r + 1 + - s = k\*r - 1, s = k\*r, s = k\*r + 1 + For example: ```bash java -jar ECTester.jar -t edge-cases -- cgit v1.3.1 From 2143be748effab61c04d4e0a8f8ca0833e1430d9 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 25 Jul 2018 22:26:00 +0200 Subject: Add note about Microsoft CNG support to docs. --- README.md | 1 + docs/LIBS.md | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/README.md b/README.md index daabdd9..7121027 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,7 @@ Currently supported libraries include: - Crypto++ - libtomcrypt - botan + - Microsoft CNG For more information on ECC libraries see [LIBS](docs/LIBS.md). diff --git a/docs/LIBS.md b/docs/LIBS.md index 59a183f..3d5e5e8 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -7,7 +7,6 @@ Popular libraries with at least some ECC support: - [Nettle](http://www.lysator.liu.se/~nisse/nettle/) - [OpenSSL (FIPS mode)](https://www.openssl.org/docs/fipsnotes.html) - BoringSSL - - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) - [Microsoft .NET crypto](https://docs.microsoft.com/en-us/dotnet/standard/security/cryptography-model) # Supported libraries @@ -77,4 +76,7 @@ Popular libraries with at least some ECC support: - For prime field curves: - Uses projective coordinates and sliding window scalar multiplication algorithm. - For binary field curves: - - Uses affine coordinates and sliding window scalar multiplication algorithm. \ No newline at end of file + - Uses affine coordinates and sliding window scalar multiplication algorithm. + - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) + - C API. + - Closed source, uses whatever. \ No newline at end of file -- cgit v1.3.1 From 0d961f0c0bdc5a0ace91bc7b2289055b26d4fbe7 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 27 Jul 2018 21:02:27 +0200 Subject: WIP: Mscng keygen works. --- .gitignore | 1 + docs/LIBS.md | 9 +- .../crcs/ectester/standalone/libs/jni/Makefile.bat | 19 +- .../standalone/libs/jni/NativeECPrivateKey.java | 10 +- .../standalone/libs/jni/NativeECPublicKey.java | 10 +- src/cz/crcs/ectester/standalone/libs/jni/c_utils.c | 4 +- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 478 +++++++++++++-------- 7 files changed, 346 insertions(+), 185 deletions(-) (limited to 'docs') diff --git a/.gitignore b/.gitignore index 90700ba..f40221d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Built artifacts in /dist and /applet. +/build/ /dist/lib/ /dist/ECTesterReader.jar /dist/ECTesterReader-dist.jar diff --git a/docs/LIBS.md b/docs/LIBS.md index 3d5e5e8..d1a68d0 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -79,4 +79,11 @@ Popular libraries with at least some ECC support: - Uses affine coordinates and sliding window scalar multiplication algorithm. - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) - C API. - - Closed source, uses whatever. \ No newline at end of file + - Closed source. + - For prime field curves(only supports): + - Uses Short Weierstrass model. + - Uses Twisted Edwards model. + - Uses Montgomery model. + - Uses fixed window scalar multiplication. + - Uses Wnaf multi-scalar multiplication with interleaving. + - Uses Montgomery ladder. \ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat index a279750..e337e70 100755 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat @@ -1,6 +1,11 @@ @if not defined _echo echo off setlocal EnableDelayedExpansion +:: ENV variables respected: +:: - JAVA_HOME +:: - CC +:: - USE_EXT_MSCNG + :: See if we are cleaning. if "%1" == "clean" ( echo ** cleaning @@ -58,8 +63,8 @@ if exist %vc_base% ( :: Get the paths to Microsoft CNG SDK. set root_rel=..\..\..\..\..\..\..\ -set mscng_rel_include=ext\mscng\Include -set mscng_rel_lib=ext\mscng\Lib +set mscng_rel_include=ext\mscng\10\Include +set mscng_rel_lib=ext\mscng\10\Lib pushd %root_rel% pushd %mscng_rel_include% @@ -115,15 +120,25 @@ if exist %ucrt_base% ( set ucrt_lib_arch=!ucrt_lib!\ucrt\%ARCH_S% ) + :: Setup INCLUDE paths. set INCLUDE_CLI=/I. /I"%JNI_INCLUDEDIR%" /I"%JNI_PLATFORMINCLUDEDIR%" +if defined USE_EXT_MSCNG ( + set INCLUDE_CLI=!INCLUDE_CLI! /I"%mscng_include%" +) + echo ** INCLUDE %INCLUDE% echo ** INCLUDE_CLI %INCLUDE_CLI% + :: Setup LIB paths. set LIBPATH=/LIBPATH:"%JNI_LIBDIR%" +if defined USE_EXT_MSCNG ( + set LIBPATH=!LIBPATH! /LIBPATH:"%mscng_lib_arch%" +) + echo ** LIB %LIB% echo ** LIBPATH %LIBPATH% echo. diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java index 7980773..76786fe 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java @@ -43,7 +43,7 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { public Raw(byte[] keyData, ECParameterSpec params) { super("EC", "raw", params); - this.keyData = keyData; + this.keyData = Arrays.clone(keyData); } @Override @@ -92,9 +92,9 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { public Mscng(byte[] header, byte[] x, byte[] y, byte[] keyData, ECParameterSpec params) { super(keyData, params); - this.header = header; - this.x = x; - this.y = y; + this.header = Arrays.clone(header); + this.x = Arrays.clone(x); + this.y = Arrays.clone(y); } public byte[] getHeader() { @@ -102,7 +102,7 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { } public byte[] getBlob() { - return ByteUtil.concatenate(header, x, y, keyData); + return ByteUtil.concatenate(header, x, y, keyData); } @Override diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java index e44ff49..e55ed33 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java @@ -45,7 +45,7 @@ public abstract class NativeECPublicKey implements ECPublicKey { public ANSIX962(byte[] keyData, ECParameterSpec params) { super("EC", "ANSI X9.62", params); - this.keyData = keyData; + this.keyData = Arrays.clone(keyData); } @Override @@ -94,9 +94,9 @@ public abstract class NativeECPublicKey implements ECPublicKey { public Mscng(byte[] header, byte[] x, byte[] y, ECParameterSpec params) { super(ByteUtil.concatenate(new byte[]{0x04}, x, y), params); - this.header = header; - this.x = x; - this.y = y; + this.header = Arrays.clone(header); + this.x = Arrays.clone(x); + this.y = Arrays.clone(y); } public byte[] getHeader() { @@ -104,7 +104,7 @@ public abstract class NativeECPublicKey implements ECPublicKey { } public byte[] getBlob() { - return ByteUtil.concatenate(header, x, y); + return ByteUtil.concatenate(header, x, y); } @Override diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c index 9fee530..f920fc4 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c @@ -21,7 +21,7 @@ void init_classes(JNIEnv *env, const char* lib_name) { ecgen_parameter_spec_class = (*env)->NewGlobalRef(env, local_ecgen_parameter_spec_class); const char *pubkey_base = "cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey$"; - char pubkey_class_name[1024]; //strlen(pubkey_base) + strlen(lib_name) + 1 + char pubkey_class_name[2048] = { 0 }; //strlen(pubkey_base) + strlen(lib_name) + 1 pubkey_class_name[0] = 0; strcat(pubkey_class_name, pubkey_base); strcat(pubkey_class_name, lib_name); @@ -30,7 +30,7 @@ void init_classes(JNIEnv *env, const char* lib_name) { pubkey_class = (*env)->NewGlobalRef(env, local_pubkey_class); const char *privkey_base = "cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey$"; - char privkey_class_name[1024]; //strlen(privkey_base) + strlen(lib_name) + 1 + char privkey_class_name[2048] = { 0 }; //strlen(privkey_base) + strlen(lib_name) + 1 privkey_class_name[0] = 0; strcat(privkey_class_name, privkey_base); strcat(privkey_class_name, lib_name); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 56502da..b0b71be 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -33,7 +33,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createP jstring name = (*env)->NewStringUTF(env, "Microsoft CNG"); double version = 1.0; - printf("createProvider\n"); return (*env)->NewObject(env, provider_class, init, name, version, name); } @@ -53,12 +52,11 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384"); ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112"); - printf("setup\n"); init_classes(env, "Mscng"); } typedef struct { - const char *name; + LPCSTR name; ULONG bits; } named_curve_t; @@ -120,42 +118,94 @@ static const named_curve_t* lookup_curve(const char *name) { } static const named_curve_t* lookup_curve_bits(jint bitsize) { - printf("looking up %i\n", bitsize); for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) { - printf("trying (%s, %i)\n", named_curves[i].name, named_curves[i].bits); if (bitsize == named_curves[i].bits) { - printf("got it!\n"); return &named_curves[i]; } } return NULL; } +static ULONG utf_16to8(NPSTR *out_buf, LPCWSTR in_str) { + INT result = WideCharToMultiByte(CP_UTF8, 0, in_str, -1, NULL, 0, NULL, NULL); + *out_buf = calloc(result, 1); + return WideCharToMultiByte(CP_UTF8, 0, in_str, -1, *out_buf, result, NULL, NULL); +} + +static ULONG utf_8to16(NWPSTR *out_buf, LPCSTR in_str) { + INT result = MultiByteToWideChar(CP_UTF8, 0, in_str, -1, NULL, 0); + *out_buf = calloc(result * sizeof(WCHAR), 1); + return MultiByteToWideChar(CP_UTF8, 0, in_str, -1, *out_buf, result); +} + +// Convert Java String to UTF-16 LPCWSTR null-terminated. +// Returns: Length of LPCWSTR in bytes! +static ULONG utf_strto16(NWPSTR *out_buf, JNIEnv *env, jobject str) { + jsize len = (*env)->GetStringLength(env, str); + *out_buf = calloc(len * sizeof(jchar) + 1, 1); + const jchar *chars = (*env)->GetStringChars(env, str, NULL); + memcpy(*out_buf, chars, len * sizeof(jchar)); + (*env)->ReleaseStringChars(env, str, chars); + return len * sizeof(jchar); +} + JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves(JNIEnv *env, jobject self) { - jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet"); + jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet"); - jmethodID hash_set_ctr = (*env)->GetMethodID(env, hash_set_class, "", "()V"); - jmethodID hash_set_add = (*env)->GetMethodID(env, hash_set_class, "add", "(Ljava/lang/Object;)Z"); + jmethodID hash_set_ctr = (*env)->GetMethodID(env, hash_set_class, "", "()V"); + jmethodID hash_set_add = (*env)->GetMethodID(env, hash_set_class, "add", "(Ljava/lang/Object;)Z"); - jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr); + jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr); - for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { - jstring curve_name = (*env)->NewStringUTF(env, named_curves[i].name); - (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name); - } - printf("getCurves\n"); + NTSTATUS status; + BCRYPT_ALG_HANDLE handle; + + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, BCRYPT_ECDH_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return 0; + } + + ULONG bufSize; + if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, NULL, 0, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptGetProperty(length only)\n", status); + return 0; + } + + BCRYPT_ECC_CURVE_NAMES *curves = (BCRYPT_ECC_CURVE_NAMES *)calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, (PBYTE) curves, bufSize, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptGetProperty(whole)\n", status); + return 0; + } + for (size_t i = 0; i < curves->dwEccCurveNames; ++i) { + NPSTR curve_name; + ULONG len = utf_16to8(&curve_name, curves->pEccCurveNames[i]); + jstring c_name = (*env)->NewStringUTF(env, curve_name); + (*env)->CallBooleanMethod(env, result, hash_set_add, c_name); + free(curve_name); + } + + free(curves); + + BCryptCloseAlgorithmProvider(handle, 0); return result; } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { - printf("keysizeSupported\n"); - return (lookup_curve_bits(keysize) == NULL) ? JNI_FALSE : JNI_TRUE; + switch (keysize) { + case 256: + case 384: + case 521: + return JNI_TRUE; + default: + return JNI_FALSE; + } } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported(JNIEnv *env, jobject self, jobject params) { - printf("paramsSupported\n"); if (params == NULL) { - printf("theyNull\n"); return JNI_FALSE; } @@ -203,41 +253,20 @@ static void biginteger_to_bytes(JNIEnv *env, jobject bigint, PBYTE bytes, ULONG (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT); } -static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLength) { - // Taken from https://github.com/dotnet/corefx, thanks! This API is nowhere to be found. +static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLength) { // - // BCRYPT_ECC_PARAMETER_HEADER header - // byte[cbFieldLength] P - // byte[cbFieldLength] A - // byte[cbFieldLength] B - // byte[cbFieldLength] G.X - // byte[cbFieldLength] G.Y - // byte[cbSubgroupOrder] Order (n) - // byte[cbCofactor] Cofactor (h) - // byte[cbSeed] Seed - - // BCRYPT_ECC_PARAMETER_HEADER - // internal int Version; //Version of the structure - // internal ECC_CURVE_TYPE_ENUM CurveType; //Supported curve types. - // internal ECC_CURVE_ALG_ID_ENUM CurveGenerationAlgId; //For X.592 verification purposes, if we include Seed we will need to include the algorithm ID. - // internal int cbFieldLength; //Byte length of the fields P, A, B, X, Y. - // internal int cbSubgroupOrder; //Byte length of the subgroup. - // internal int cbCofactor; //Byte length of cofactor of G in E. - // internal int cbSeed; //Byte length of the seed used to generate the curve. - - // internal enum ECC_CURVE_TYPE_ENUM : int - // { - // BCRYPT_ECC_PRIME_SHORT_WEIERSTRASS_CURVE = 0x1, - // BCRYPT_ECC_PRIME_TWISTED_EDWARDS_CURVE = 0x2, - // BCRYPT_ECC_PRIME_MONTGOMERY_CURVE = 0x3, - // } - - // internal enum ECC_CURVE_ALG_ID_ENUM : int - // { - // BCRYPT_NO_CURVE_GENERATION_ALG_ID = 0x0, - // } - BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)eccParams; - PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; + // BCRYPT_ECCFULLKEY_BLOB header + // P[cbFieldLength] Prime specifying the base field. + // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p + // B[cbFieldLength] Coefficient B of the equation y^2 = x^3 + A*x + B mod p + // Gx[cbFieldLength] X-coordinate of the base point. + // Gy[cbFieldLength] Y-coordinate of the base point. + // n[cbSubgroupOrder] Order of the group generated by G = (x,y) + // h[cbCofactor] Cofactor of G in E. + // S[cbSeed] Seed of the curve. + + BCRYPT_ECCFULLKEY_BLOB *header = (BCRYPT_ECCFULLKEY_BLOB*)eccParams; + PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECCFULLKEY_BLOB)]; //cbFieldLength PBYTE P = paramsStart; @@ -255,6 +284,8 @@ static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLen //cbSeed PBYTE S = H + header->cbCofactor; + *paramLength = sizeof(BCRYPT_ECCFULLKEY_BLOB) + 5 * header->cbFieldLength + header->cbSubgroupOrder + header->cbCofactor + header->cbSeed; + jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength); jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "", "(Ljava/math/BigInteger;)V"); @@ -322,7 +353,7 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { jint order_bytes = (order_bits + 7) / 8; // header_size + 5*bytes + order_bytes + cof_size + 0 - ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5*bytes + order_bytes + sizeof(jint) + 0; + ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5*bytes + order_bytes + 1 + 0; *curve = calloc(bufSize, 1); BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve; header->dwVersion = 1; @@ -330,7 +361,7 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { header->dwCurveGenerationAlgId = 0; header->cbFieldLength = bytes; header->cbSubgroupOrder = order_bytes; - header->cbCofactor = sizeof(jint); + header->cbCofactor = 1; header->cbSeed = 0; PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; @@ -341,14 +372,16 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { biginteger_to_bytes(env, gx, paramsStart + 3*bytes, bytes); biginteger_to_bytes(env, gy, paramsStart + 4*bytes, bytes); biginteger_to_bytes(env, n, paramsStart + 5*bytes, order_bytes); - jint *cof_ptr = (jint *) (paramsStart + 5*bytes + order_bytes); - *cof_ptr = h; + PBYTE cof_ptr = (PBYTE) (paramsStart + 5*bytes + order_bytes); + *cof_ptr = (BYTE)h; return bufSize; } static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, jobject params) { - if (NT_FAILURE(BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + NTSTATUS status; + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); return 0; } ULONG result = 0; @@ -359,17 +392,22 @@ static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, job PUCHAR chars = calloc(utf_length + 1, 1); (*env)->GetStringUTFRegion(env, name, 0, utf_length, chars); const named_curve_t *curve = lookup_curve(chars); - if (NT_FAILURE(BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, chars, strlen(chars), 0))) { + NWPSTR curve_utf16; + ULONG ret = utf_8to16(&curve_utf16, chars); + if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, (PUCHAR) curve_utf16, ret * sizeof(WCHAR), 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status); return 0; } free(chars); + free(curve_utf16); result = curve->bits; } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { PBYTE curve; ULONG curveLen = create_curve(env, params, &curve); - if (NT_FAILURE(BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { + if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status); return 0; } free(curve); @@ -382,31 +420,62 @@ static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, job jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I"); jint bits = (*env)->CallIntMethod(env, field, get_bits); - result = (bits + 7) / 8; + result = bits; } return result; } -static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { +static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { + NTSTATUS status; ULONG bufSize = 0; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status); + return NULL; } if (bufSize == 0) { //err + printf("err0\n"); + return NULL; } - PBYTE privBuf = calloc(bufSize, 1); - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufSize, &bufSize, 0))) { + PBYTE fullBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, fullBuf, bufSize, &bufSize, 0))) { //err - } + wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status); + return NULL; + } + + ULONG paramLength; + jobject ec_priv_param_spec = create_ec_param_spec(env, fullBuf, ¶mLength); + free(fullBuf); + + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(length only)\n", status); + return NULL; + } + + PBYTE privBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufSize, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(whole)\n", status); + return NULL; + } + + printf("generate length %lu\n", bufSize); + printf("generated privkey: "); + for (size_t i = 0; i < bufSize; ++i) { + printf("%02x", (unsigned)privBuf[i] & 0xffU); + } + printf("\n"); // privBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] Q.X - // byte[cbKey] Q.Y - // byte[cbKey] D - BCRYPT_ECCKEY_BLOB *privHeader = (BCRYPT_ECCKEY_BLOB*)privBuf; + // BCRYPT_ECCKEY_BLOB header + // Qx[cbKey] X-coordinate of the public point. + // Qy[cbKey] Y-coordinate of the public point. + // d[cbKey] Private key. + BCRYPT_ECCKEY_BLOB *privHeader = (BCRYPT_ECCKEY_BLOB*)privBuf; PBYTE priv_x = &privBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; PBYTE priv_y = priv_x + privHeader->cbKey; PBYTE priv = priv_y + privHeader->cbKey; @@ -432,28 +501,54 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_par (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); free(privBuf); - - jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec); - jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[BLjava/security/spec/ECParameterSpec;)V"); + + jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[B[B[BLjava/security/spec/ECParameterSpec;)V"); return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); } -static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { +static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { + NTSTATUS status; ULONG bufSize = 0; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status); + return NULL; } + if (bufSize == 0) { + //err + printf("err0\n"); + return NULL; + } - PBYTE pubBuf = calloc(bufSize, 1); - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, pubBuf, bufSize, &bufSize, 0))) { + PBYTE fullBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, fullBuf, bufSize, &bufSize, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status); + return NULL; } - // pubBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] Q.X - // byte[cbKey] Q.Y - BCRYPT_ECCKEY_BLOB *pubHeader = (BCRYPT_ECCKEY_BLOB*)pubBuf; + ULONG paramLength; + jobject ec_pub_param_spec = create_ec_param_spec(env, fullBuf, ¶mLength); + free(fullBuf); + + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(length only)\n", status); + return NULL; + } + + PBYTE pubBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, pubBuf, bufSize, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(whole)\n", status); + return NULL; + } + + // pubBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // Qx[cbKey] X-coordinate of the public point. + // Qy[cbKey] Y-coordinate of the public point. + BCRYPT_ECCKEY_BLOB *pubHeader = (BCRYPT_ECCKEY_BLOB*)pubBuf; PBYTE pub_x = &pubBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; PBYTE pub_y = pub_x + pubHeader->cbKey; @@ -474,22 +569,85 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_para free(pubBuf); - jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec); jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { - throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); - return NULL; + NTSTATUS status; + BCRYPT_ALG_HANDLE handle = NULL; + + jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); + jstring type = (jstring)(*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR algo; + if (strcmp(type_data, "ECDH") == 0) { + switch (keysize) { + case 256: + algo = BCRYPT_ECDH_P256_ALGORITHM; + break; + case 384: + algo = BCRYPT_ECDH_P384_ALGORITHM; + break; + case 521: + algo = BCRYPT_ECDH_P521_ALGORITHM; + break; + default: + //err + break; + } + } else if (strcmp(type_data, "ECDSA") == 0) { + switch (keysize) { + case 256: + algo = BCRYPT_ECDSA_P256_ALGORITHM; + break; + case 384: + algo = BCRYPT_ECDSA_P384_ALGORITHM; + break; + case 521: + algo = BCRYPT_ECDSA_P521_ALGORITHM; + break; + default: + //err + break; + } + } else { + //err + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return NULL; + } + + BCRYPT_KEY_HANDLE key = NULL; + + if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, keysize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptGenerateKeyPair\n", status); + } + + if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptFinalizeKeyPair\n", status); + } + + jobject privkey = key_to_privkey(env, key); + jobject pubkey = key_to_pubkey(env, key); + + jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + + BCryptDestroyKey(key); + BCryptCloseAlgorithmProvider(handle, 0); + return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ - BCRYPT_ALG_HANDLE kaHandle = NULL; + NTSTATUS status; + BCRYPT_ALG_HANDLE handle = NULL; BCRYPT_KEY_HANDLE key = NULL; - fprintf(stderr, "1\n"); - fflush(stderr); jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); @@ -500,74 +658,37 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai } else if (strcmp(type_data, "ECDSA") == 0) { algo = BCRYPT_ECDSA_ALGORITHM; } else { - fprintf(stderr, "err\n"); - fflush(stderr); + //err } (*env)->ReleaseStringUTFChars(env, type, type_data); - fprintf(stderr, "2\n"); - fflush(stderr); - ULONG bits = init_algo(env, &kaHandle, algo, params); + ULONG bits = init_algo(env, &handle, algo, params); if (bits == 0) { - fprintf(stderr, "err0\n"); - fflush(stderr); - } - - fprintf(stderr, "3\n"); - fflush(stderr); - ULONG paramsSize; - if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, NULL, 0, ¶msSize, 0))) { - fprintf(stderr, "err\n"); - fflush(stderr); - } - if (paramsSize == 0) { - fprintf(stderr, "err0\n"); - fflush(stderr); - } - - fprintf(stderr, "4\n"); - fflush(stderr); - PBYTE eccParams = calloc(paramsSize, 1); - if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, eccParams, paramsSize, ¶msSize, 0))) { - fprintf(stderr, "err\n"); - fflush(stderr); + //err } - jobject ec_param_spec = create_ec_param_spec(env, eccParams, paramsSize); - - free(eccParams); - - fprintf(stderr, "5\n"); - fflush(stderr); - if (NT_FAILURE(BCryptGenerateKeyPair(kaHandle, &key, bits, 0))) { - fprintf(stderr, "err\n"); - fflush(stderr); + if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, bits, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptGenerateKeyPair\n", status); } - fprintf(stderr, "6\n"); - fflush(stderr); - if (NT_FAILURE(BCryptFinalizeKeyPair(key, 0))) { - fprintf(stderr, "err\n"); - fflush(stderr); + if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptFinalizeKeyPair\n", status); } - jobject privkey = key_to_privkey(env, key, ec_param_spec); - jobject pubkey = key_to_pubkey(env, key, ec_param_spec); + jobject privkey = key_to_privkey(env, key); + jobject pubkey = key_to_pubkey(env, key); - fprintf(stderr, "7\n"); - fflush(stderr); jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); - fprintf(stderr, "8\n"); - fflush(stderr); BCryptDestroyKey(key); - BCryptCloseAlgorithmProvider(kaHandle, 0); - fprintf(stderr, "9\n"); - fflush(stderr); + BCryptCloseAlgorithmProvider(handle, 0); return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { + NTSTATUS status; + printf("generateSecret!\n"); + jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;"); jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); @@ -597,22 +718,22 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey jint pub_length = (*env)->GetArrayLength(env, pubkey); jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { - //err + if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair(pub)\n", status); } (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); jint priv_length = (*env)->GetArrayLength(env, privkey); jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { - //err + if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair(priv)\n", status); } (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); BCRYPT_SECRET_HANDLE ka = NULL; - if (NT_FAILURE(BCryptSecretAgreement(skey, pkey, &ka, 0))) { - //err + if (NT_FAILURE(status = BCryptSecretAgreement(skey, pkey, &ka, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptSecretAgreement\n", status); } BCryptBufferDesc paramList = {0}; @@ -626,13 +747,13 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey //TODO: Is this the actual KDF-1 or KDF-2 algo or something completely different? *This does not use the counter!!!* ULONG bufSize = 0; - if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { - //err + if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptDeriveKey(length only)\n", status); } PBYTE derived = calloc(bufSize, 1); - if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { - //err + if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptDeriveKey(whole)\n", status); } jbyteArray result = (*env)->NewByteArray(env, bufSize); @@ -671,32 +792,34 @@ static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) { } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { + NTSTATUS status; LPCWSTR hash_algo = get_sighash_algo(env, self); BCRYPT_ALG_HANDLE sigHandle = NULL; if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { //err + printf("init err!\n"); } BCRYPT_ALG_HANDLE hashHandle = NULL; - if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { - //err + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); } DWORD dummy = 0; DWORD hash_len = 0; - if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { - //err + if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptGetProperty(hash len)\n", status); } PBYTE hash = calloc(hash_len, 1); jint data_len = (*env)->GetArrayLength(env, data); jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - //err + if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + wprintf(L"**** Error 0x%x returned by BCryptHash\n", status); } (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); @@ -704,20 +827,27 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jint priv_length = (*env)->GetArrayLength(env, privkey); jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { - //err + + printf("priv_length %i\n", priv_length); + printf("using privkey: "); + for (size_t i = 0; i < priv_length; ++i) { + printf("%02x", (unsigned)priv_data[i] & 0xffU); + } + printf("\n"); + if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status); } (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); DWORD sig_len = 0; - if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { - //err + if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptSignHash(len only)\n", status); } jbyteArray sig = (*env)->NewByteArray(env, sig_len); jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); - if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { - //err + if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptSignHash(do)\n", status); } (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0); @@ -731,6 +861,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) { + NTSTATUS status; LPCWSTR hash_algo = get_sighash_algo(env, self); BCRYPT_ALG_HANDLE sigHandle = NULL; @@ -741,22 +872,22 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna BCRYPT_ALG_HANDLE hashHandle = NULL; - if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { - //err + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); } DWORD dummy = 0; DWORD hash_len = 0; - if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { - //err + if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptGetProperty(hash len)\n", status); } PBYTE hash = calloc(hash_len, 1); jint data_len = (*env)->GetArrayLength(env, data); jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - //err + if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + wprintf(L"**** Error 0x%x returned by BCryptHash\n", status); } (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); @@ -764,8 +895,15 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jint pub_length = (*env)->GetArrayLength(env, pubkey); jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &pkey, pub_data, pub_length, 0))) { - //err + + printf("pub_length %i\n", pub_length); + printf("using pubkey: "); + for (size_t i = 0; i < pub_length; ++i) { + printf("%02x", (unsigned)pub_data[i] & 0xffU); + } + printf("\n"); + if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status); } (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); @@ -785,7 +923,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } else if (result == STATUS_INVALID_SIGNATURE) { return JNI_FALSE; } else { - //err + wprintf(L"**** Error 0x%x returned by BCryptVerifySignature\n", status); return JNI_FALSE; } } \ No newline at end of file -- cgit v1.3.1