aboutsummaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/standalone
diff options
context:
space:
mode:
Diffstat (limited to 'src/cz/crcs/ectester/standalone')
-rw-r--r--src/cz/crcs/ectester/standalone/ECTesterStandalone.java169
-rw-r--r--src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java54
-rw-r--r--src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java4
-rw-r--r--src/cz/crcs/ectester/standalone/libs/CryptoppLib.java20
-rw-r--r--src/cz/crcs/ectester/standalone/libs/MscngLib.java20
-rw-r--r--src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java3
-rw-r--r--src/cz/crcs/ectester/standalone/libs/OpensslLib.java19
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/Makefile83
-rwxr-xr-xsrc/cz/crcs/ectester/standalone/libs/jni/Makefile.bat163
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java78
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java79
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java151
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java97
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java40
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java179
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/botan.cpp244
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/c_utils.c14
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/c_utils.h20
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp24
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp8
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp732
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/mscng.c1210
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/native.h1201
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/openssl.c567
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c42
-rw-r--r--src/cz/crcs/ectester/standalone/output/TextTestWriter.java31
-rw-r--r--src/cz/crcs/ectester/standalone/output/XMLTestWriter.java63
-rw-r--r--src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java65
-rw-r--r--src/cz/crcs/ectester/standalone/test/KeyAgreementTestable.java124
-rw-r--r--src/cz/crcs/ectester/standalone/test/SignatureTestable.java107
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java (renamed from src/cz/crcs/ectester/standalone/test/KeyAgreementTest.java)18
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java170
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java (renamed from src/cz/crcs/ectester/standalone/test/KeyGeneratorTest.java)15
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java (renamed from src/cz/crcs/ectester/standalone/test/KeyGeneratorTestable.java)44
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/SignatureTest.java (renamed from src/cz/crcs/ectester/standalone/test/SignatureTest.java)15
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/SignatureTestable.java130
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/StandaloneTestable.java25
-rw-r--r--src/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java (renamed from src/cz/crcs/ectester/standalone/test/StandaloneDefaultSuite.java)46
-rw-r--r--src/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java (renamed from src/cz/crcs/ectester/standalone/test/StandaloneTestSuite.java)12
39 files changed, 5057 insertions, 1029 deletions
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index f5361c3..31d291c 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -1,3 +1,25 @@
+/*
+ * ECTester, tool for testing Elliptic curve cryptography implementations.
+ * Copyright (c) 2016-2018 Petr Svenda <petr@svenda.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
package cz.crcs.ectester.standalone;
import cz.crcs.ectester.common.cli.*;
@@ -14,14 +36,15 @@ import cz.crcs.ectester.standalone.libs.*;
import cz.crcs.ectester.standalone.output.TextTestWriter;
import cz.crcs.ectester.standalone.output.XMLTestWriter;
import cz.crcs.ectester.standalone.output.YAMLTestWriter;
-import cz.crcs.ectester.standalone.test.StandaloneDefaultSuite;
-import cz.crcs.ectester.standalone.test.StandaloneTestSuite;
+import cz.crcs.ectester.standalone.test.suites.StandaloneDefaultSuite;
+import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
@@ -31,6 +54,7 @@ import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.util.*;
import java.util.stream.Collectors;
@@ -39,18 +63,18 @@ import java.util.stream.Collectors;
* Standalone part of ECTester, a tool for testing Elliptic curve implementations in software libraries.
*
* @author Jan Jancar johny@neuromancer.sk
- * @version v0.1.0
+ * @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(), new OpensslLib(), new MscngLib()};
private Config cfg;
private Options opts = new Options();
private TreeParser optParser;
private TreeCommandLine cli;
- private static final String VERSION = "v0.1.0";
+ public static final String VERSION = "v0.2.0";
private static final String DESCRIPTION = "ECTesterStandalone " + VERSION + ", an Elliptic Curve Cryptography support tester/utility.";
- private static final String LICENSE = "MIT Licensed\nCopyright (c) 2016-2017 Petr Svenda <petr@svenda.com>";
+ private static final String LICENSE = "MIT Licensed\nCopyright (c) 2016-2018 Petr Svenda <petr@svenda.com>";
private static final String CLI_HEADER = "\n" + DESCRIPTION + "\n\n";
private static final String CLI_FOOTER = "\n" + LICENSE;
@@ -79,6 +103,8 @@ public class ECTesterStandalone {
listLibraries();
} else if (cli.isNext("list-data")) {
CLITools.listNamed(EC_Store.getInstance(), cli.getNext().getArg(0));
+ } else if (cli.isNext("list-suites")) {
+ listSuites();
} else if (cli.isNext("ecdh")) {
ecdh();
} else if (cli.isNext("ecdsa")) {
@@ -98,7 +124,7 @@ public class ECTesterStandalone {
} catch (NoSuchAlgorithmException nsaex) {
System.err.println("Algorithm not supported by the selected library: " + nsaex.getMessage());
nsaex.printStackTrace();
- } catch (InvalidKeyException | SignatureException | TestException e) {
+ } catch (InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
@@ -106,68 +132,80 @@ public class ECTesterStandalone {
private TreeCommandLine parseArgs(String[] args) throws ParseException {
Map<String, ParserOptions> actions = new TreeMap<>();
- Option namedCurve = Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: <cat/id>").hasArg().argName("cat/id").build();
+ Option namedCurve = Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: <cat/id>").hasArg().argName("cat/id").optionalArg(false).build();
+ Option curveName = Option.builder("cn").longOpt("curve-name").desc("Use a named curve, search from curves supported by the library: <name>").hasArg().argName("name").optionalArg(false).build();
Option bits = Option.builder("b").longOpt("bits").hasArg().argName("n").optionalArg(false).desc("What size of curve to use.").build();
Options testOpts = new Options();
testOpts.addOption(bits);
testOpts.addOption(namedCurve);
+ testOpts.addOption(curveName);
testOpts.addOption(Option.builder("gt").longOpt("kpg-type").desc("Set the KeyPairGenerator object [type].").hasArg().argName("type").optionalArg(false).build());
testOpts.addOption(Option.builder("kt").longOpt("ka-type").desc("Set the KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build());
testOpts.addOption(Option.builder("st").longOpt("sig-type").desc("Set the Signature object [type].").hasArg().argName("type").optionalArg(false).build());
testOpts.addOption(Option.builder("f").longOpt("format").desc("Set the output format, one of text,yaml,xml.").hasArg().argName("format").optionalArg(false).build());
+ testOpts.addOption(Option.builder().longOpt("key-type").desc("Set the key [algorithm] for which the key should be derived in KeyAgreements with KDF. Default is \"AES\".").hasArg().argName("algorithm").optionalArg(false).build());
List<Argument> testArgs = new LinkedList<>();
- testArgs.add(new Argument("test_suite", "The test suite to run.", true));
- ParserOptions test = new ParserOptions(new DefaultParser(), testOpts, testArgs);
+ testArgs.add(new Argument("test-suite", "The test suite to run.", true));
+ ParserOptions test = new ParserOptions(new TreeParser(Collections.emptyMap(), true, testArgs), testOpts, "Test a library.");
actions.put("test", test);
Options ecdhOpts = new Options();
ecdhOpts.addOption(bits);
ecdhOpts.addOption(namedCurve);
+ ecdhOpts.addOption(curveName);
ecdhOpts.addOption(Option.builder("t").longOpt("type").desc("Set KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build());
+ ecdhOpts.addOption(Option.builder().longOpt("key-type").desc("Set the key [algorithm] for which the key should be derived in KeyAgreements with KDF. Default is \"AES\".").hasArg().argName("algorithm").optionalArg(false).build());
ecdhOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDH [amount] times.").build());
- ParserOptions ecdh = new ParserOptions(new DefaultParser(), ecdhOpts);
+ ParserOptions ecdh = new ParserOptions(new DefaultParser(), ecdhOpts, "Perform EC based KeyAgreement.");
actions.put("ecdh", ecdh);
Options ecdsaOpts = new Options();
ecdsaOpts.addOption(bits);
ecdsaOpts.addOption(namedCurve);
+ ecdsaOpts.addOption(curveName);
ecdsaOpts.addOption(Option.builder("t").longOpt("type").desc("Set Signature object [type].").hasArg().argName("type").optionalArg(false).build());
ecdsaOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDSA [amount] times.").build());
ecdsaOpts.addOption(Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build());
- ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts);
+ ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts, "Perform EC based Signature.");
actions.put("ecdsa", ecdsa);
Options generateOpts = new Options();
generateOpts.addOption(bits);
generateOpts.addOption(namedCurve);
+ generateOpts.addOption(curveName);
generateOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Generate [amount] of EC keys.").build());
generateOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPairGenerator object [type].").build());
- ParserOptions generate = new ParserOptions(new DefaultParser(), generateOpts);
+ ParserOptions generate = new ParserOptions(new DefaultParser(), generateOpts, "Generate EC keypairs.");
actions.put("generate", generate);
Options exportOpts = new Options();
- exportOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPair object [type].").build());
exportOpts.addOption(bits);
- ParserOptions export = new ParserOptions(new DefaultParser(), exportOpts);
+ exportOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPair object [type].").build());
+ ParserOptions export = new ParserOptions(new DefaultParser(), exportOpts, "Export default curve parameters.");
actions.put("export", export);
Options listDataOpts = new Options();
List<Argument> listDataArgs = new LinkedList<>();
listDataArgs.add(new Argument("what", "what to list.", false));
- ParserOptions listData = new ParserOptions(new TreeParser(Collections.emptyMap(), false, listDataArgs), listDataOpts);
+ ParserOptions listData = new ParserOptions(new TreeParser(Collections.emptyMap(), false, listDataArgs), listDataOpts, "List/show contained EC domain parameters/keys.");
actions.put("list-data", listData);
Options listLibsOpts = new Options();
- ParserOptions listLibs = new ParserOptions(new DefaultParser(), listLibsOpts);
+ ParserOptions listLibs = new ParserOptions(new DefaultParser(), listLibsOpts, "List supported libraries.");
actions.put("list-libs", listLibs);
+ Options listSuitesOpts = new Options();
+ ParserOptions listSuites = new ParserOptions(new DefaultParser(), listSuitesOpts, "List supported test suites.");
+ actions.put("list-suites", listSuites);
+
List<Argument> baseArgs = new LinkedList<>();
baseArgs.add(new Argument("lib", "What library to use.", false));
optParser = new TreeParser(actions, false, baseArgs);
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);
}
@@ -176,24 +214,24 @@ public class ECTesterStandalone {
*
*/
private void listLibraries() {
- for (ECLibrary lib : libs) {
+ 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<KeyPairGeneratorIdent> 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<KeyAgreementIdent> 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<SignatureIdent> 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<String> 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();
}
@@ -203,10 +241,24 @@ public class ECTesterStandalone {
/**
*
*/
+ private void listSuites() {
+ StandaloneTestSuite[] suites = new StandaloneTestSuite[]{new StandaloneDefaultSuite(null, null, null)};
+ for (StandaloneTestSuite suite : suites) {
+ System.out.println(" - " + suite.getName());
+ for (String line : suite.getDescription()) {
+ System.out.println("\t" + line);
+ }
+ }
+ }
+
+ /**
+ *
+ */
private void ecdh() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException {
ProviderECLibrary lib = cfg.selected;
String algo = cli.getOptionValue("ecdh.type", "ECDH");
+ String keyAlgo = cli.getOptionValue("ecdh.key-type", "AES");
KeyAgreementIdent kaIdent = lib.getKAs().stream()
.filter((ident) -> ident.contains(algo))
.findFirst()
@@ -223,7 +275,6 @@ public class ECTesterStandalone {
.findFirst()
.orElse(null)));
-
if (kaIdent == null || kpIdent == null) {
throw new NoSuchAlgorithmException(algo);
} else {
@@ -242,7 +293,11 @@ public class ECTesterStandalone {
}
spec = curve.toSpec();
kpg.initialize(spec);
- }//TODO: allow ECGenNamedSpec
+ } else if (cli.hasOption("ecdh.curve-name")) {
+ String curveName = cli.getOptionValue("ecdh.curve-name");
+ spec = new ECGenParameterSpec(curveName);
+ kpg.initialize(spec);
+ }
System.out.println("index;nanotime;pubW;privS;secret");
@@ -262,7 +317,16 @@ public class ECTesterStandalone {
}
ka.doPhase(pubkey, true);
elapsed += System.nanoTime();
- byte[] result = ka.generateSecret();
+ SecretKey derived;
+ byte[] result;
+ elapsed -= System.nanoTime();
+ if (kaIdent.requiresKeyAlgo()) {
+ derived = ka.generateSecret(keyAlgo);
+ result = derived.getEncoded();
+ } else {
+ result = ka.generateSecret();
+ }
+ elapsed += System.nanoTime();
ka = kaIdent.getInstance(lib.getProvider());
String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
@@ -327,6 +391,9 @@ public class ECTesterStandalone {
return;
}
kpg.initialize(curve.toSpec());
+ } else if (cli.hasOption("ecdsa.curve-name")) {
+ String curveName = cli.getOptionValue("ecdsa.curve-name");
+ kpg.initialize(new ECGenParameterSpec(curveName));
}
System.out.println("index;data;signtime;verifytime;pubW;privS;signature;verified");
@@ -389,6 +456,9 @@ public class ECTesterStandalone {
return;
}
kpg.initialize(curve.toSpec());
+ } else if (cli.hasOption("generate.curve-name")) {
+ String curveName = cli.getOptionValue("generate.curve-name");
+ kpg.initialize(new ECGenParameterSpec(curveName));
}
System.out.println("index;nanotime;pubW;privS");
@@ -410,7 +480,7 @@ public class ECTesterStandalone {
/**
*
*/
- private void test() throws NoSuchAlgorithmException, TestException, ParserConfigurationException {
+ private void test() throws TestException, ParserConfigurationException {
TestWriter writer;
switch (cli.getOptionValue("test.format", "text").toLowerCase()) {
case "yaml":
@@ -434,7 +504,7 @@ public class ECTesterStandalone {
*
*/
private void export() throws NoSuchAlgorithmException, IOException {
- ProviderECLibrary lib = (ProviderECLibrary) cfg.selected;
+ ProviderECLibrary lib = cfg.selected;
KeyPairGeneratorIdent ident = null;
String algo = cli.getOptionValue("export.type", "EC");
for (KeyPairGeneratorIdent kpIdent : lib.getKPGs()) {
@@ -472,12 +542,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.");
@@ -485,28 +559,33 @@ public class ECTesterStandalone {
}
String next = cli.getNextName();
- if (cli.hasOption(next + ".bits") && cli.hasOption(next + ".named-curve")) {
- System.err.println("You can only specify bitsize or a named curve, nor both.");
+ boolean hasBits = cli.hasOption(next + ".bits");
+ boolean hasNamedCurve = cli.hasOption(next + ".named-curve");
+ boolean hasCurveName = cli.hasOption(next + ".curve-name");
+ if (hasBits ^ hasNamedCurve ? hasCurveName : hasBits) {
+ System.err.println("You can only specify bitsize or a named curve/curve name, nor both.");
return false;
}
}
- String libraryName = cli.getArg(-1);
- if (libraryName != null) {
- List<ProviderECLibrary> matchedLibs = new LinkedList<>();
- for (ProviderECLibrary lib : libs) {
- if (lib.name().toLowerCase().contains(libraryName.toLowerCase())) {
- matchedLibs.add(lib);
+ if (!cli.isNext("list-data") && !cli.isNext("list-suites")) {
+ String libraryName = cli.getArg(-1);
+ if (libraryName != null) {
+ List<ProviderECLibrary> matchedLibs = new LinkedList<>();
+ for (ProviderECLibrary lib : libs) {
+ if (lib.isInitialized() && lib.name().toLowerCase().contains(libraryName.toLowerCase())) {
+ matchedLibs.add(lib);
+ }
+ }
+ if (matchedLibs.size() == 0) {
+ System.err.println("No library " + libraryName + " found.");
+ return false;
+ } else if (matchedLibs.size() > 1) {
+ System.err.println("Multiple matching libraries found: " + String.join(",", matchedLibs.stream().map(ECLibrary::name).collect(Collectors.toList())));
+ return false;
+ } else {
+ selected = matchedLibs.get(0);
}
- }
- if (matchedLibs.size() == 0) {
- System.err.println("No library " + libraryName + " found.");
- return false;
- } else if (matchedLibs.size() > 1) {
- System.err.println("Multiple matching libraries found: " + String.join(",", matchedLibs.stream().map(ECLibrary::name).collect(Collectors.toList())));
- return false;
- } else {
- selected = matchedLibs.get(0);
}
}
diff --git a/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java b/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java
index 0e4d311..94e8c84 100644
--- a/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java
+++ b/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java
@@ -10,6 +10,8 @@ import java.util.List;
* @author Jan Jancar johny@neuromancer.sk
*/
public class KeyAgreementIdent extends Ident {
+ private boolean requiresKeyAlgo;
+
private static final List<KeyAgreementIdent> ALL = new LinkedList<>();
static {
@@ -18,23 +20,36 @@ public class KeyAgreementIdent extends Ident {
ALL.add(new KeyAgreementIdent("ECDH"));
ALL.add(new KeyAgreementIdent("ECDHC", "ECCDH"));
// ECDH and ECDHC with SHA as KDF, OIDs from RFC 3278
- ALL.add(new KeyAgreementIdent("ECDHwithSHA1KDF", "1.3.133.16.840.63.0.2"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA1KDF", "1.3.133.16.840.63.0.3"));
- ALL.add(new KeyAgreementIdent("ECDHwithSHA224KDF", "1.3.132.1.11.0"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA224KDF", "1.3.132.1.14.0"));
- ALL.add(new KeyAgreementIdent("ECDHwithSHA256KDF", "1.3.132.1.11.1"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA256KDF", "1.3.132.1.14.1"));
- ALL.add(new KeyAgreementIdent("ECDHwithSHA384KDF", "1.3.132.1.11.2"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA384KDF", "1.3.132.1.14.2"));
- ALL.add(new KeyAgreementIdent("ECDHwithSHA512KDF", "1.3.132.1.11.3"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA512KDF", "1.3.132.1.14.3"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA1KDF", true, "1.3.133.16.840.63.0.2"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA1KDF", true, "1.3.133.16.840.63.0.3"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA224KDF",true, "1.3.132.1.11.0"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA224KDF", true, "1.3.132.1.14.0"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA256KDF", true, "1.3.132.1.11.1"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA256KDF", true, "1.3.132.1.14.1"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA384KDF", true, "1.3.132.1.11.2"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA384KDF", true, "1.3.132.1.14.2"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA512KDF", true, "1.3.132.1.11.3"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA512KDF", true, "1.3.132.1.14.3"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA1CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA1CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA256CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA256CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA384CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA384CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA512CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA512CKDF", true));
// ECMQV - Disable for now as it needs diferent params(too different from DH)
//ALL.add(new KeyAgreementIdent("ECMQV"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA1CKDF", "1.3.133.16.840.63.0.16"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA224CKDF", "1.3.132.1.15.0"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA256CKDF", "1.3.132.1.15.1"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA384CKDF", "1.3.132.1.15.2"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA512CKDF", "1.3.132.1.15.3"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA1KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA224KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA256KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA354KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA512KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA1CKDF", true, "1.3.133.16.840.63.0.16"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA224CKDF", true, "1.3.132.1.15.0"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA256CKDF", true, "1.3.132.1.15.1"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA384CKDF", true, "1.3.132.1.15.2"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA512CKDF", true, "1.3.132.1.15.3"));
// ECVKO - Disable for now as it needs diferent params(too different from DH)
//ALL.add(new KeyAgreementIdent("ECVKO", "ECGOST3410", "1.2.643.2.2.19", "GOST-3410-2001", "1.2.643.2.2.96"));
//ALL.add(new KeyAgreementIdent("ECVKO256", "ECGOST3410-2012-256", "1.2.643.7.1.1.6.1", "1.2.643.7.1.1.1.1"));
@@ -54,6 +69,15 @@ public class KeyAgreementIdent extends Ident {
super(name, aliases);
}
+ private KeyAgreementIdent(String name, boolean requiresKeyAlgo, String... aliases) {
+ this(name, aliases);
+ this.requiresKeyAlgo = requiresKeyAlgo;
+ }
+
+ public boolean requiresKeyAlgo() {
+ return requiresKeyAlgo;
+ }
+
public KeyAgreement getInstance(Provider provider) throws NoSuchAlgorithmException {
KeyAgreement instance = getInstance((algorithm, provider1) -> {
try {
diff --git a/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java b/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java
index 8e67967..332b78e 100644
--- a/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java
+++ b/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java
@@ -15,8 +15,8 @@ public class KeyPairGeneratorIdent extends Ident {
ALL.add(new KeyPairGeneratorIdent("ECDSA"));
ALL.add(new KeyPairGeneratorIdent("ECDHC"));
ALL.add(new KeyPairGeneratorIdent("ECMQV"));
- ALL.add(new KeyPairGeneratorIdent("ECGOST3410"));
- ALL.add(new KeyPairGeneratorIdent("ECGOST3410-2012"));
+ //ALL.add(new KeyPairGeneratorIdent("ECGOST3410"));
+ //ALL.add(new KeyPairGeneratorIdent("ECGOST3410-2012"));
// ECKCDSA? Botan provides.
ALL.add(new KeyPairGeneratorIdent("ECKCDSA"));
// ECGDSA? Botan provides.
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<String> getCurves();
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/MscngLib.java b/src/cz/crcs/ectester/standalone/libs/MscngLib.java
new file mode 100644
index 0000000..527a65b
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/MscngLib.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 MscngLib extends NativeECLibrary {
+
+ public MscngLib() {
+ super("mscng_provider", "bcrypt");
+ }
+
+ @Override
+ native Provider createProvider();
+
+ @Override
+ public native Set<String> getCurves();
+}
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;
}
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<String> getCurves();
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
index 3530499..006a3b1 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile
+++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
@@ -1,32 +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)
@@ -36,13 +36,27 @@ LOCAL_LIBS = /usr/local/lib
CC?=gcc
CXX?=g++
+STRIP?=strip
-CFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
-CXXFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+LFLAGS+=-fPIC -shared
+CFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+CXXFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+DEBUG ?= 0
+
+ifeq ($(DEBUG), 1)
+ CFLAGS+=-g
+ LFLAGS+=-g
+ CXXFLAGS+=-g
+else
+ CFLAGS+=-O2
+ LFLAGS+=-O2
+ CXXFLAGS+=-O2
+endif
-all: tomcrypt_provider.so botan_provider.so
+all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so
+# Common utils
c_utils.o: c_utils.c
$(CC) $(CFLAGS) -c $<
@@ -50,18 +64,37 @@ cpp_utils.o: cpp_utils.cpp
$(CXX) $(CXXFLAGS) -c $<
+# OpenSSL shim
+openssl_provider.so: openssl.o c_utils.o
+ $(CC) $(LFLAGS) -o $@ $^ -L. $(shell pkg-config --libs openssl)
+
+openssl.o: openssl.c
+ $(CC) $(shell pkg-config --cflags openssl) $(CFLAGS) -c $<
+
+
+# Libtomcrypt shim
tomcrypt_provider.so: tomcrypt.o c_utils.o
- $(CC) -fPIC -g -shared -o $@ $^ -L. -ltommath -ltomcrypt
+ $(CC) $(LFLAGS) -o $@ $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt)
tomcrypt.o: tomcrypt.c
- $(CC) -DLTM_DESC $(CFLAGS) -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. -L"$(LOCAL_LIBS)" -lbotan-2 -fstack-protector -m64 -pthread
+ $(CXX) $(LFLAGS) -o $@ $^ -L. $(shell pkg-config --libs botan-2)
botan.o: botan.cpp
- $(CXX) -I"$(LOCAL_INCLUDES)/botan-2" $(CFLAGS) -c $<
+ $(CXX) $(shell pkg-config --cflags botan-2) $(CXXFLAGS) -c $<
+
+
+# Crypto++ shim
+cryptopp_provider.so: cryptopp.o cpp_utils.o
+ $(CXX) $(LFLAGS) -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/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat
new file mode 100755
index 0000000..9b0d6f7
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat
@@ -0,0 +1,163 @@
+@if not defined _echo echo off
+setlocal EnableDelayedExpansion
+
+:: ENV variables respected:
+:: - JAVA_HOME
+:: - CC
+:: - USE_EXT_MSCNG
+:: - DEBUG
+
+:: See if we are cleaning.
+if "%1" == "clean" (
+ echo ** cleaning
+ del *.dll *.exp *.lib *.obj
+ exit
+)
+
+set TAB=
+
+
+:: Determine arch.
+reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL 2>&1 && (set ARCH=32& set ARCH_S=x86& set ARCH_VS=x86) || (set ARCH=64& set ARCH_S=x64& set ARCH_VS=amd64)
+
+echo ** ARCH%TAB%%TAB%%ARCH_S%
+
+
+:: Find a working visual studio environment.
+set found=0
+set vsw_path="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
+
+set vs_path=
+for /f "usebackq delims=" %%i in (`%vsw_path% -nologo -prerelease -latest -property installationPath`) do (
+ if exist "%%i\Common7\Tools\vsdevcmd.bat" (
+ echo ** VsDevCmd%TAB%%TAB%%%i\Common7\Tools\vsdevcmd.bat
+ call "%%i\Common7\Tools\vsdevcmd.bat" -no_logo -arch=%ARCH_VS%
+ if ERRORLEVEL 1 (
+ echo nope.
+ ) else (
+ set found=1
+ set vs_path=%%i
+ break
+ )
+ )
+)
+
+:: Test if we have a visual studio env.
+if %found% EQU 0 (
+ echo Working VsDevCmd not found.
+ exit /b 2
+)
+
+echo ** VS_PATH%TAB%%TAB%%vs_path%
+
+
+:: Try to find vcruntime.
+set vc_base=%vs_path%\VC\Tools\MSVC\
+if exist %vc_base% (
+ set vc_version=
+ for /f "delims=" %%i in ('dir /b /on "!vc_base!"') do (
+ set vc_version=%%i
+ )
+ echo ** VC_VERSION%TAB%!vc_version!
+ set vc_include=%vc_base%!vc_version!\include
+ set vc_lib=%vc_base%!vc_version!\lib\%ARCH_S%
+)
+
+
+:: Get the paths to Microsoft CNG SDK.
+set root_rel=..\..\..\..\..\..\..\
+set mscng_rel_include=ext\mscng\10\Include
+set mscng_rel_lib=ext\mscng\10\Lib
+
+pushd %root_rel%
+pushd %mscng_rel_include%
+set mscng_include=%CD%
+popd
+pushd %mscng_rel_lib%
+set mscng_lib=%CD%
+popd
+popd
+
+set mscng_lib_arch=%mscng_lib%\X%ARCH%
+
+echo ** CNG_INCLUDE%TAB%%mscng_include%
+echo ** CNG_LIB%TAB%%TAB%%mscng_lib_arch%
+
+
+:: Get the paths to Java JNI.
+if not defined JAVA_HOME (
+ set jva=
+ for /f "delims=" %%i in ('where javac') do (
+ set jva=%%~dpi
+ )
+ pushd !jva!\..
+ set JAVA_HOME=!CD!
+ popd
+)
+
+echo ** JAVA_HOME%TAB%%JAVA_HOME%
+
+set JNI_INCLUDEDIR=%JAVA_HOME%\include
+set JNI_PLATFORMINCLUDEDIR=%JNI_INCLUDEDIR%\win32
+set JNI_LIBDIR=%JAVA_HOME%\lib
+
+
+:: Setup binaries.
+if not defined CC (
+ set CC=cl.exe
+)
+
+echo ** CC%TAB%%TAB%%CC%
+
+
+:: Try to find uCRT.
+set ucrt_base=%ProgramFiles(x86)%\Windows Kits\10\
+if exist %ucrt_base% (
+ set ucrt_version=
+ for /f "delims=" %%i in ('dir /b /on "!ucrt_base!\Include"') do (
+ set ucrt_version=%%i
+ )
+ echo ** uCRT%TAB%%TAB%!ucrt_version!
+ set ucrt_include=%ucrt_base%Include\!ucrt_version!\ucrt
+ set ucrt_lib=%ucrt_base%Lib\!ucrt_version!
+ 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%TAB%%TAB%%INCLUDE%
+echo ** INCLUDE_CLI%TAB%%INCLUDE_CLI%
+
+
+:: Setup LIB paths.
+set LIBPATH=/LIBPATH:"%JNI_LIBDIR%"
+
+if defined USE_EXT_MSCNG (
+ set LIBPATH=!LIBPATH! /LIBPATH:"%mscng_lib_arch%"
+)
+
+echo ** LIB%TAB%%TAB%%LIB%
+echo ** LIBPATH%TAB%%TAB%%LIBPATH%
+
+
+:: Setup DEBUB options.
+set OTHER_CLI=
+if defined DEBUG (
+ set OTHER_CLI=/Od /Z7
+) else (
+ set OTHER_CLI=/O2
+)
+
+echo ** OTHER_CLI%TAB%%OTHER_CLI%
+echo.
+
+echo ^>^> %CC% /W2 /EHsc %OTHER_CLI% %INCLUDE_CLI% mscng.c c_utils.c bcrypt.lib jvm.lib /Femscng_provider.dll /LD /link %LIBPATH% /nologo
+echo.
+
+%CC% /W2 /EHsc %OTHER_CLI% %INCLUDE_CLI% mscng.c c_utils.c bcrypt.lib jvm.lib /Femscng_provider.dll /LD /link %LIBPATH% /nologo \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
index 22e5329..4cd4a9d 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
@@ -1,5 +1,6 @@
package cz.crcs.ectester.standalone.libs.jni;
+import cz.crcs.ectester.common.util.ByteUtil;
import org.bouncycastle.util.Arrays;
import java.math.BigInteger;
@@ -12,10 +13,12 @@ import java.security.spec.ECParameterSpec;
public abstract class NativeECPrivateKey implements ECPrivateKey {
private String algorithm;
private String format;
+ ECParameterSpec params;
- public NativeECPrivateKey(String algorithm, String format) {
+ public NativeECPrivateKey(String algorithm, String format, ECParameterSpec params) {
this.algorithm = algorithm;
this.format = format;
+ this.params = params;
}
@Override
@@ -28,14 +31,19 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
return format;
}
+ @Override
+ public ECParameterSpec getParams() {
+ return params;
+ }
+
+ public abstract byte[] getData();
+
private static class Raw extends NativeECPrivateKey {
- private byte[] keyData;
- private ECParameterSpec params;
+ byte[] keyData;
public Raw(byte[] keyData, ECParameterSpec params) {
- super("EC", "raw");
- this.keyData = keyData;
- this.params = params;
+ super("EC", "raw", params);
+ this.keyData = Arrays.clone(keyData);
}
@Override
@@ -48,9 +56,8 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
return Arrays.clone(keyData);
}
- @Override
- public ECParameterSpec getParams() {
- return params;
+ public byte[] getData() {
+ return getEncoded();
}
}
@@ -65,4 +72,57 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
super(keyData, params);
}
}
+
+ public static class Cryptopp extends Raw {
+ public Cryptopp(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
+ public static class Openssl extends Raw {
+ public Openssl(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
+ public static class Mscng extends Raw {
+ // 0 -> implicit (meta = curveName UTF16, header = full);
+ // 1 -> explicit (meta = null, header = full);
+ // 2 -> nist (meta = null, header = full)
+ private int flag;
+ private byte[] meta = null;
+ private byte[] header;
+ private byte[] x;
+ private byte[] y;
+
+ public Mscng(int flag, byte[] meta, byte[] header, byte[] x, byte[] y, byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ this.flag = flag;
+ this.meta = Arrays.clone(meta);
+ this.header = Arrays.clone(header);
+ this.x = Arrays.clone(x);
+ this.y = Arrays.clone(y);
+ }
+
+ public int getFlag() {
+ return flag;
+ }
+
+ public byte[] getMeta() {
+ return Arrays.clone(meta);
+ }
+
+ public byte[] getHeader() {
+ return Arrays.clone(header);
+ }
+
+ public byte[] getBlob() {
+ return ByteUtil.concatenate(header, x, y, keyData);
+ }
+
+ @Override
+ public byte[] getData() {
+ return getBlob();
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
index 8fc4747..ccf21c0 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
@@ -1,8 +1,10 @@
package cz.crcs.ectester.standalone.libs.jni;
+import cz.crcs.ectester.common.util.ByteUtil;
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;
@@ -13,10 +15,12 @@ import java.security.spec.ECPoint;
public abstract class NativeECPublicKey implements ECPublicKey {
private String algorithm;
private String format;
+ ECParameterSpec params;
- public NativeECPublicKey(String algorithm, String format) {
+ public NativeECPublicKey(String algorithm, String format, ECParameterSpec params) {
this.algorithm = algorithm;
this.format = format;
+ this.params = params;
}
@Override
@@ -29,14 +33,19 @@ public abstract class NativeECPublicKey implements ECPublicKey {
return format;
}
+ @Override
+ public ECParameterSpec getParams() {
+ return params;
+ }
+
+ public abstract byte[] getData();
+
private static class ANSIX962 extends NativeECPublicKey {
- private byte[] keyData;
- private ECParameterSpec params;
+ byte[] keyData;
public ANSIX962(byte[] keyData, ECParameterSpec params) {
- super("EC", "ANSI X9.62");
- this.keyData = keyData;
- this.params = params;
+ super("EC", "ANSI X9.62", params);
+ this.keyData = Arrays.clone(keyData);
}
@Override
@@ -49,9 +58,8 @@ public abstract class NativeECPublicKey implements ECPublicKey {
return Arrays.clone(keyData);
}
- @Override
- public ECParameterSpec getParams() {
- return params;
+ public byte[] getData() {
+ return ECUtil.toX962Uncompressed(getW(), params);
}
}
@@ -66,4 +74,57 @@ public abstract class NativeECPublicKey implements ECPublicKey {
super(keyData, params);
}
}
+
+ public static class Cryptopp extends ANSIX962 {
+ public Cryptopp(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
+ public static class Openssl extends ANSIX962 {
+ public Openssl(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
+ public static class Mscng extends ANSIX962 {
+ // 0 -> implicit (meta = curveName UTF16, header = full);
+ // 1 -> explicit (meta = null, header = full);
+ // 2 -> nist (meta = null, header = full)
+ private int flag;
+ private byte[] meta = null;
+ private byte[] header;
+ private byte[] x;
+ private byte[] y;
+
+ public Mscng(int flag, byte[] meta, byte[] header, byte[] x, byte[] y, ECParameterSpec params) {
+ super(ByteUtil.concatenate(new byte[]{0x04}, x, y), params);
+ this.flag = flag;
+ this.meta = Arrays.clone(meta);
+ this.header = Arrays.clone(header);
+ this.x = Arrays.clone(x);
+ this.y = Arrays.clone(y);
+ }
+
+ public int getFlag() {
+ return flag;
+ }
+
+ public byte[] getMeta() {
+ return Arrays.clone(meta);
+ }
+
+ public byte[] getHeader() {
+ return Arrays.clone(header);
+ }
+
+ public byte[] getBlob() {
+ return ByteUtil.concatenate(header, x, y);
+ }
+
+ @Override
+ public byte[] getData() {
+ return getBlob();
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
index 37c9add..4ed3469 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
@@ -5,19 +5,21 @@ import cz.crcs.ectester.common.util.ECUtil;
import javax.crypto.KeyAgreementSpi;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
+import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
+import java.security.spec.ECGenParameterSpec;
/**
* @author Jan Jancar johny@neuromancer.sk
*/
public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
- private ECPrivateKey privateKey;
- private ECPublicKey publicKey;
- private ECParameterSpec params;
+ ECPrivateKey privateKey;
+ ECPublicKey publicKey;
+ AlgorithmParameterSpec params;
@Override
protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
@@ -30,15 +32,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
}
@Override
- protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
- if (!(params instanceof ECParameterSpec)) {
- throw new InvalidAlgorithmParameterException();
- }
- engineInit(key, random);
- this.params = (ECParameterSpec) params;
- }
-
- @Override
protected Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException {
if (privateKey == null) {
throw new IllegalStateException("Not initialized");
@@ -59,13 +52,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
}
@Override
- protected byte[] engineGenerateSecret() throws IllegalStateException {
- byte[] pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), params.getCurve());
- byte[] privkey = ECUtil.toByteArray(privateKey.getS(), params.getCurve().getField().getFieldSize());
- return generateSecret(pubkey, privkey, params);
- }
-
- @Override
protected int engineGenerateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException {
byte[] secret = engineGenerateSecret();
if (sharedSecret.length < offset + secret.length) {
@@ -77,20 +63,70 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
@Override
protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException {
- throw new NoSuchAlgorithmException(algorithm);
+ // TODO: This is dangerous/not correct ! Need to actually implement KDF1 and KDF2 here probably. Or just pass it off to the libs through some different interface.
+ return new SecretKeySpec(engineGenerateSecret(), algorithm);
}
- abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+ private abstract static class SimpleKeyAgreementSpi extends NativeKeyAgreementSpi {
+
+ @Override
+ protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (!(params instanceof ECParameterSpec)) {
+ throw new InvalidAlgorithmParameterException();
+ }
+ engineInit(key, random);
+ this.params = params;
+ }
+
+ @Override
+ protected byte[] engineGenerateSecret() throws IllegalStateException {
+ byte[] pubkey;
+ if (publicKey instanceof NativeECPublicKey) {
+ pubkey = ((NativeECPublicKey) publicKey).getData();
+ } else {
+ pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), ((ECParameterSpec) params).getCurve());
+ }
+ byte[] privkey;
+ if (privateKey instanceof NativeECPrivateKey) {
+ privkey = ((NativeECPrivateKey) privateKey).getData();
+ } else {
+ privkey = ECUtil.toByteArray(privateKey.getS(), ((ECParameterSpec) params).getCurve().getField().getFieldSize());
+ }
+ return generateSecret(pubkey, privkey, (ECParameterSpec) params);
+ }
+
+ abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+ }
+
+ private abstract static class ExtendedKeyAgreementSpi extends NativeKeyAgreementSpi {
+
+ @Override
+ protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (!(params instanceof ECParameterSpec || params instanceof ECGenParameterSpec)) {
+ throw new InvalidAlgorithmParameterException();
+ }
+ engineInit(key, random);
+ this.params = params;
+ }
+
+ @Override
+ protected byte[] engineGenerateSecret() throws IllegalStateException {
+ return generateSecret(publicKey, privateKey, params);
+ }
+
+ abstract byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params);
+ }
- public static class TomCrypt extends NativeKeyAgreementSpi {
+ public static class TomCrypt extends SimpleKeyAgreementSpi {
@Override
native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
}
- public abstract static class Botan extends NativeKeyAgreementSpi {
+ public abstract static class Botan extends SimpleKeyAgreementSpi {
private String type;
+
public Botan(String type) {
this.type = type;
}
@@ -134,4 +170,73 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
super("ECDHwithSHA512KDF");
}
}
+
+ public abstract static class Cryptopp extends SimpleKeyAgreementSpi {
+ 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");
+ }
+ }
+
+ public abstract static class Openssl extends SimpleKeyAgreementSpi {
+ private String type;
+
+ public Openssl(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+ }
+
+ public static class OpensslECDH extends Openssl {
+ public OpensslECDH() {
+ super("ECDH");
+ }
+ }
+
+ public abstract static class Mscng extends ExtendedKeyAgreementSpi {
+ private String type;
+
+ public Mscng(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params);
+ }
+
+ public static class MscngECDHwithSHA1KDF extends Mscng {
+ public MscngECDHwithSHA1KDF() {
+ super("ECDHwithSHA1KDF");
+ }
+ }
+
+ public static class MscngECDHwithSHA256KDF extends Mscng {
+ public MscngECDHwithSHA256KDF() {
+ super("ECDHwithSHA256KDF");
+ }
+ }
+
+ public static class MscngECDHwithSHA384KDF extends Mscng {
+ public MscngECDHwithSHA384KDF() {
+ super("ECDHwithSHA384KDF");
+ }
+ }
+
+ public static class MscngECDHwithSHA512KDF extends Mscng {
+ public MscngECDHwithSHA512KDF() {
+ super("ECDHwithSHA512KDF");
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
index 9461251..7ca013a 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
@@ -27,7 +27,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
@Override
public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException {
if (!paramsSupported(params)) {
- throw new InvalidAlgorithmParameterException("not supported.");
+ throw new InvalidAlgorithmParameterException("Not supported.");
}
this.params = params;
this.random = random;
@@ -41,8 +41,9 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
return generate(keysize, random);
} else if (useParams) {
return generate(params, random);
+ } else {
+ throw new IllegalStateException("Uninitialized KeyPair.");
}
- return null;
}
abstract boolean keysizeSupported(int keysize);
@@ -56,7 +57,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
public static class TomCrypt extends NativeKeyPairGeneratorSpi {
public TomCrypt() {
- initialize(256, new SecureRandom());
+ initialize(256, new SecureRandom());//TODO: maybe remove this default init?
}
@Override
@@ -77,7 +78,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
public Botan(String type) {
this.type = type;
- initialize(256, new SecureRandom());
+ initialize(256, new SecureRandom());//TODO: maybe remove this default init?
}
@Override
@@ -120,4 +121,92 @@ 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());//TODO: maybe remove this default init?
+ }
+
+ @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 Cryptopp {
+
+ public CryptoppECDH() {
+ super("ECDH");
+ }
+ }
+
+ public static class CryptoppECDSA extends Cryptopp {
+
+ public CryptoppECDSA() {
+ 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);
+ }
+
+ public static abstract class Mscng extends NativeKeyPairGeneratorSpi {
+ private String type;
+
+ public Mscng(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 MscngECDH extends Mscng {
+
+ public MscngECDH() {
+ super("ECDH");
+ }
+ }
+
+ public static class MscngECDSA extends Mscng {
+
+ public MscngECDSA() {
+ super("ECDSA");
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
index a0689d6..fef2930 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
@@ -12,10 +12,14 @@ public abstract class NativeProvider extends Provider {
public NativeProvider(String name, double version, String info) {
super(name, version, info);
- AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
+ if (System.getSecurityManager() == null) {
setup();
- return null;
- });
+ } else {
+ AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
+ setup();
+ return null;
+ });
+ }
}
abstract void setup();
@@ -39,4 +43,34 @@ 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();
+ }
+
+ public static class Openssl extends NativeProvider {
+
+ public Openssl(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ @Override
+ native void setup();
+ }
+
+ public static class Mscng extends NativeProvider {
+
+ public Mscng(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ @Override
+ native void setup();
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
index b212697..b60f2c6 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
@@ -12,11 +12,11 @@ import java.security.spec.ECParameterSpec;
* @author Jan Jancar johny@neuromancer.sk
*/
public abstract class NativeSignatureSpi extends SignatureSpi {
- private ECPublicKey verifyKey;
- private ECPrivateKey signKey;
- private ECParameterSpec params;
+ ECPublicKey verifyKey;
+ ECPrivateKey signKey;
+ ECParameterSpec params;
- private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
@Override
protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
@@ -50,15 +50,6 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
buffer.write(b, off, len);
}
- @Override
- protected byte[] engineSign() throws SignatureException {
- return sign(buffer.toByteArray(), ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize()), params);
- }
-
- @Override
- protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
- return verify(sigBytes, buffer.toByteArray(), ECUtil.toX962Uncompressed(verifyKey.getW(), params), params);
- }
@Override
@Deprecated
@@ -72,11 +63,53 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
throw new UnsupportedOperationException("getParameter() not supported");
}
- abstract byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+ private abstract static class SimpleSignatureSpi extends NativeSignatureSpi {
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ byte[] privkey;
+ if (signKey instanceof NativeECPrivateKey) {
+ privkey = ((NativeECPrivateKey) signKey).getData();
+ } else {
+ privkey = ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize());
+ }
+ return sign(buffer.toByteArray(), privkey, params);
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ byte[] pubkey;
+ if (verifyKey instanceof NativeECPublicKey) {
+ pubkey = ((NativeECPublicKey) verifyKey).getData();
+ } else {
+ pubkey = ECUtil.toX962Uncompressed(verifyKey.getW(), params);
+ }
+ return verify(sigBytes, buffer.toByteArray(), pubkey, params);
+ }
- abstract boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ abstract byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
- public static class TomCryptRaw extends NativeSignatureSpi {
+ abstract boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ }
+
+ private abstract static class ExtendedSignatureSpi extends NativeSignatureSpi {
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ return sign(buffer.toByteArray(), signKey, params);
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ return verify(sigBytes, buffer.toByteArray(), verifyKey, params);
+ }
+
+ abstract byte[] sign(byte[] data, ECPrivateKey privkey, ECParameterSpec params);
+
+ abstract boolean verify(byte[] signature, byte[] data, ECPublicKey pubkey, ECParameterSpec params);
+ }
+
+ public static class TomCryptRaw extends SimpleSignatureSpi {
@Override
native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
@@ -85,7 +118,7 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
}
- public abstract static class Botan extends NativeSignatureSpi {
+ public abstract static class Botan extends SimpleSignatureSpi {
private String type;
public Botan(String type) {
@@ -224,4 +257,116 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
super("SHA512withECGDSA");
}
}
+
+ public abstract static class Cryptopp extends SimpleSignatureSpi {
+ private String type;
+
+ public Cryptopp(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ }
+
+ public static class CryptoppECDSAwithSHA1 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA1() {
+ super("SHA1withECDSA");
+ }
+ }
+
+ public static class CryptoppECDSAwithSHA224 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA224() {
+ super("SHA224withECDSA");
+ }
+ }
+
+ public static class CryptoppECDSAwithSHA256 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA256() {
+ super("SHA256withECDSA");
+ }
+ }
+
+ public static class CryptoppECDSAwithSHA384 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA384() {
+ super("SHA384withECDSA");
+ }
+ }
+
+ public static class CryptoppECDSAwithSHA512 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA512() {
+ super("SHA512withECDSA");
+ }
+ }
+
+ public abstract static class Openssl extends SimpleSignatureSpi {
+ private String type;
+
+ public Openssl(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ }
+
+ public static class OpensslECDSAwithNONE extends Openssl {
+
+ public OpensslECDSAwithNONE() {
+ super("NONEwithECDSA");
+ }
+ }
+
+ public abstract static class Mscng extends ExtendedSignatureSpi {
+ private String type;
+
+ public Mscng(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] sign(byte[] data, ECPrivateKey privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, ECPublicKey pubkey, ECParameterSpec params);
+ }
+
+ public static class MscngECDSAwithSHA1 extends Mscng {
+
+ public MscngECDSAwithSHA1() {
+ super("SHA1withECDSA");
+ }
+ }
+
+ public static class MscngECDSAwithSHA256 extends Mscng {
+
+ public MscngECDSAwithSHA256() {
+ super("SHA256withECDSA");
+ }
+ }
+
+ public static class MscngECDSAwithSHA384 extends Mscng {
+
+ public MscngECDSAwithSHA384() {
+ super("SHA384withECDSA");
+ }
+ }
+
+ public static class MscngECDSAwithSHA512 extends Mscng {
+
+ public MscngECDSAwithSHA512() {
+ super("SHA512withECDSA");
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
index 8e666d6..d506ecd 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
+++ b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
@@ -1,6 +1,14 @@
#include "native.h"
#include <string>
-#include <botan/botan.h>
+
+#include <botan/lookup.h>
+#include <botan/version.h>
+#include <botan/parsing.h>
+#include <botan/init.h>
+#include <botan/rng.h>
+#include <botan/secmem.h>
+#include <botan/auto_rng.h>
+
#include <botan/ec_group.h>
#include <botan/ecc_key.h>
#include <botan/ecdsa.h>
@@ -12,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");
@@ -36,166 +39,67 @@ 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;");
- 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);
+ 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);
- 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);
+ 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);
- 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);
+ 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);
- 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_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");
}
-/*
- * 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 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, "<init>", "()V");
- jmethodID hash_set_add = env->GetMethodID(hash_set_class, "add", "(Ljava/lang/Object;)Z");
+ jmethodID set_ctr = env->GetMethodID(set_class, "<init>", "()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<std::string>& 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;
}
-/*
- * 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;
@@ -230,7 +134,7 @@ static jobject biginteger_from_bigint(JNIEnv *env, const Botan::BigInt& bigint)
jbyteArray bigint_array = env->NewByteArray(bigint_data.size());
jbyte * bigint_bytes = env->GetByteArrayElements(bigint_array, NULL);
std::copy(bigint_data.begin(), bigint_data.end(), bigint_bytes);
- env->ReleaseByteArrayElements(bigint_array, bigint_bytes, JNI_COMMIT);
+ env->ReleaseByteArrayElements(bigint_array, bigint_bytes, 0);
jmethodID biginteger_init = env->GetMethodID(biginteger_class, "<init>", "(I[B)V");
return env->NewObject(biginteger_class, biginteger_init, (jint) 1, bigint_array);
@@ -285,16 +189,14 @@ static Botan::EC_Group group_from_params(JNIEnv *env, jobject params) {
Botan::BigInt pi = bigint_from_biginteger(env, p);
Botan::BigInt ai = bigint_from_biginteger(env, a);
Botan::BigInt bi = bigint_from_biginteger(env, b);
- Botan::CurveGFp curve(pi, ai, bi);
Botan::BigInt gxi = bigint_from_biginteger(env, gx);
Botan::BigInt gyi = bigint_from_biginteger(env, gy);
- Botan::PointGFp generator(curve, gxi, gyi);
Botan::BigInt ni = bigint_from_biginteger(env, n);
Botan::BigInt hi(h);
- return Botan::EC_Group(curve, generator, ni, hi);
+ return Botan::EC_Group(pi, ai, bi, gxi, gyi, ni, hi);
} else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) {
jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
jstring name = (jstring) env->CallObjectMethod(params, get_name);
@@ -307,14 +209,13 @@ static Botan::EC_Group group_from_params(JNIEnv *env, jobject params) {
}
static jobject params_from_group(JNIEnv *env, Botan::EC_Group group) {
- const Botan::CurveGFp& curve = group.get_curve();
- jobject p = biginteger_from_bigint(env, curve.get_p());
+ jobject p = biginteger_from_bigint(env, group.get_p());
jmethodID fp_field_init = env->GetMethodID(fp_field_class, "<init>", "(Ljava/math/BigInteger;)V");
jobject fp_field = env->NewObject(fp_field_class, fp_field_init, p);
- jobject a = biginteger_from_bigint(env, curve.get_a());
- jobject b = biginteger_from_bigint(env, curve.get_b());
+ jobject a = biginteger_from_bigint(env, group.get_a());
+ jobject b = biginteger_from_bigint(env, group.get_b());
jmethodID elliptic_curve_init = env->GetMethodID(elliptic_curve_class, "<init>", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
jobject elliptic_curve = env->NewObject(elliptic_curve_class, elliptic_curve_init, fp_field, a, b);
@@ -365,12 +266,12 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
jobject ec_param_spec = params_from_group(env, group);
const Botan::PointGFp& pub_point = skey->public_point();
- std::vector<uint8_t> pub_data = Botan::unlock(Botan::EC2OSP(pub_point, Botan::PointGFp::UNCOMPRESSED));
+ std::vector<uint8_t> pub_data = pub_point.encode(Botan::PointGFp::UNCOMPRESSED);
jbyteArray pub_bytearray = env->NewByteArray(pub_data.size());
jbyte *pub_bytes = env->GetByteArrayElements(pub_bytearray, NULL);
std::copy(pub_data.begin(), pub_data.end(), pub_bytes);
- env->ReleaseByteArrayElements(pub_bytearray, pub_bytes, JNI_COMMIT);
+ env->ReleaseByteArrayElements(pub_bytearray, pub_bytes, 0);
jobject ec_pub_param_spec = env->NewLocalRef(ec_param_spec);
jmethodID ec_pub_init = env->GetMethodID(pubkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
@@ -382,7 +283,7 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
jbyteArray priv_bytearray = env->NewByteArray(priv_data.size());
jbyte *priv_bytes = env->GetByteArrayElements(priv_bytearray, NULL);
std::copy(priv_data.begin(), priv_data.end(), priv_bytes);
- env->ReleaseByteArrayElements(priv_bytearray, priv_bytes, JNI_COMMIT);
+ env->ReleaseByteArrayElements(priv_bytearray, priv_bytes, 0);
jobject ec_priv_param_spec = env->NewLocalRef(ec_param_spec);
jmethodID ec_priv_init = env->GetMethodID(privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
@@ -393,16 +294,11 @@ 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<std::string>& curves = Botan::EC_Group::known_named_groups();
for (auto it = curves.begin(); it != curves.end(); ++it) {
Botan::EC_Group curve_group = Botan::EC_Group(*it);
- size_t curve_size = curve_group.get_curve().get_p().bits();
+ size_t curve_size = curve_group.get_p_bits();
if (curve_size == keysize) {
//generate on this group. Even thou no default groups are present...
return generate_from_group(env, self, curve_group);
@@ -413,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);
@@ -442,7 +328,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
jsize pubkey_length = env->GetArrayLength(pubkey);
jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL);
- Botan::PointGFp public_point = Botan::OS2ECP((uint8_t*) pubkey_data, pubkey_length, curve_group.get_curve());
+ Botan::PointGFp public_point = curve_group.OS2ECP((uint8_t*) pubkey_data, pubkey_length);
env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT);
Botan::ECDH_PublicKey pkey(curve_group, public_point);
@@ -461,19 +347,19 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
kdf = "Raw";
//key len unused
} else if (type_str == "ECDHwithSHA1KDF") {
- kdf = "KDF1(SHA-1)";
+ kdf = "KDF2(SHA-1)";
key_len = 20;
} else if (type_str == "ECDHwithSHA224KDF") {
- kdf = "KDF1(SHA-224)";
+ kdf = "KDF2(SHA-224)";
key_len = 28;
} else if (type_str == "ECDHwithSHA256KDF") {
- kdf = "KDF1(SHA-256)";
+ kdf = "KDF2(SHA-256)";
key_len = 32;
} else if (type_str == "ECDHwithSHA384KDF") {
- kdf = "KDF1(SHA-384)";
+ kdf = "KDF2(SHA-384)";
key_len = 48;
} else if (type_str == "ECDHwithSHA512KDF") {
- kdf = "KDF1(SHA-512)";
+ kdf = "KDF2(SHA-512)";
key_len = 64;
}
@@ -489,16 +375,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
jbyteArray result = env->NewByteArray(derived.size());
jbyte *result_data = env->GetByteArrayElements(result, NULL);
std::copy(derived.begin(), derived.end(), result_data);
- env->ReleaseByteArrayElements(result, result_data, JNI_COMMIT);
+ env->ReleaseByteArrayElements(result, result_data, 0);
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);
@@ -557,16 +438,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jbyteArray result = env->NewByteArray(sig.size());
jbyte *result_data = env->GetByteArrayElements(result, NULL);
std::copy(sig.begin(), sig.end(), result_data);
- env->ReleaseByteArrayElements(result, result_data, JNI_COMMIT);
+ env->ReleaseByteArrayElements(result, result_data, 0);
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);
@@ -579,7 +455,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
jsize pubkey_length = env->GetArrayLength(pubkey);
jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL);
- Botan::PointGFp public_point = Botan::OS2ECP((uint8_t*) pubkey_data, pubkey_length, curve_group.get_curve());
+ Botan::PointGFp public_point = curve_group.OS2ECP((uint8_t*) pubkey_data, pubkey_length);
env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT);
std::unique_ptr<Botan::EC_PublicKey> pkey;
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 336f4a1..6954c36 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
@@ -1,4 +1,5 @@
#include "c_utils.h"
+#define _ISOC99_SOURCE
#include <string.h>
jclass ec_parameter_spec_class;
@@ -21,7 +22,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[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 +31,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[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);
@@ -64,3 +65,12 @@ void throw_new(JNIEnv *env, const char *class, const char *message) {
jclass clazz = (*env)->FindClass(env, class);
(*env)->ThrowNew(env, clazz, message);
}
+
+void throw_new_var(JNIEnv *env, const char *class, const char *format, ...) {
+ char buffer[2048];
+ va_list args;
+ va_start(args, format);
+ int res = vsnprintf(buffer, 2048, format, args);
+ va_end(args);
+ throw_new(env, class, buffer);
+} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
index d925dfe..2e5fa1a 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
@@ -25,4 +25,22 @@ void init_classes(JNIEnv *env, const char* lib_name);
/**
* Throw a new exception of class with message.
*/
-void throw_new(JNIEnv *env, const char *class, const char *message); \ No newline at end of file
+void throw_new(JNIEnv *env, const char *class, const char *message);
+
+/**
+ * Throw a new exception of class, with formatted message.
+ */
+void throw_new_var(JNIEnv *env, const char *class, const char *format, ...);
+
+/**
+ * Some useful defines to init the provider.
+ */
+#define INIT_PROVIDER(env, provider_class) jmethodID provider_put = (*env)->GetMethodID(env, provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
+#define ADD_PROPERTY(env, self, base_name, base_class, prop_name, prop_class) do { \
+ jstring ec = (*env)->NewStringUTF(env, base_name prop_name); \
+ jstring ec_value = (*env)->NewStringUTF(env, base_class prop_class); \
+ (*env)->CallObjectMethod(env, self, provider_put, ec, ec_value); \
+ } while (0)
+#define ADD_KPG(env, self, kpg_name, kpg_class) ADD_PROPERTY(env, self, "KeyPairGenerator.", "cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$", kpg_name, kpg_class)
+#define ADD_KA(env, self, ka_name, ka_class) ADD_PROPERTY(env, self, "KeyAgreement.", "cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$", ka_name, ka_class)
+#define ADD_SIG(env, self, sig_name, sig_class) ADD_PROPERTY(env, self, "Signature.", "cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$", sig_name, sig_class) \ No newline at end of file
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..0107d0d
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
@@ -0,0 +1,732 @@
+#include "native.h"
+
+#include <iostream>
+using std::cout;
+using std::cerr;
+using std::endl;
+
+#include <string>
+#include <sstream>
+using std::string;
+
+#include <stdexcept>
+using std::runtime_error;
+
+#include <cstdlib>
+using std::exit;
+
+#include "cryptopp/cryptlib.h"
+using CryptoPP::Exception;
+
+#include "cryptopp/config.h"
+using CryptoPP::byte;
+
+#include "cryptopp/osrng.h"
+using CryptoPP::AutoSeededRandomPool;
+using CryptoPP::AutoSeededX917RNG;
+
+#include "cryptopp/sha.h"
+using CryptoPP::SHA1;
+using CryptoPP::SHA224;
+using CryptoPP::SHA256;
+using CryptoPP::SHA384;
+using CryptoPP::SHA512;
+
+#include "cryptopp/aes.h"
+using CryptoPP::AES;
+
+#include "cryptopp/modarith.h"
+using CryptoPP::ModularArithmetic;
+
+#include "cryptopp/gf2n.h"
+using CryptoPP::PolynomialMod2;
+using CryptoPP::GF2NP;
+using CryptoPP::GF2NT;
+using CryptoPP::GF2NPP;
+
+#include "cryptopp/eccrypto.h"
+using CryptoPP::ECP;
+using CryptoPP::EC2N;
+using CryptoPP::ECDH;
+using CryptoPP::DL_GroupParameters_EC;
+using CryptoPP::ECDSA;
+
+#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;
+
+
+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, "<init>", "(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);
+}
+
+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;");
+
+ add_kpg(env, "ECDH", "CryptoppECDH", self, provider_put);
+ add_kpg(env, "ECDSA", "CryptoppECDSA", self, provider_put);
+
+ add_ka(env, "ECDH", "CryptoppECDH", self, provider_put);
+
+ add_sig(env, "SHA1withECDSA", "CryptoppECDSAwithSHA1", self, provider_put);
+ add_sig(env, "SHA224withECDSA", "CryptoppECDSAwithSHA224", self, provider_put);
+ add_sig(env, "SHA256withECDSA", "CryptoppECDSAwithSHA256", self, provider_put);
+ add_sig(env, "SHA384withECDSA", "CryptoppECDSAwithSHA384", self, provider_put);
+ add_sig(env, "SHA512withECDSA", "CryptoppECDSAwithSHA512", self, provider_put);
+
+ init_classes(env, "Cryptopp");
+}
+
+template <class EC> static std::vector<OID> get_curve_oids() {
+ std::vector<OID> oids;
+ OID it = OID();
+ do {
+ it = DL_GroupParameters_EC<EC>::GetNextRecommendedParametersOID(it);
+ if (it == OID()) {
+ break;
+ }
+ oids.push_back(it);
+ } while (true);
+
+ return oids;
+}
+
+static std::vector<OID> get_all_curve_oids() {
+ std::vector<OID> ecp_oids = get_curve_oids<ECP>();
+ std::vector<OID> ec2n_oids = get_curve_oids<EC2N>();
+
+ std::vector<OID> all_oids;
+ all_oids.insert(all_oids.end(), ecp_oids.begin(), ecp_oids.end());
+ all_oids.insert(all_oids.end(), ec2n_oids.begin(), ec2n_oids.end());
+ return all_oids;
+}
+
+static std::string oid_to_str(const OID &oid) {
+ const std::vector<CryptoPP::word32>& oid_values = oid.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]);
+ }
+ return ss.str();
+}
+
+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, "<init>", "()V");
+ jmethodID set_add = env->GetMethodID(set_class, "add", "(Ljava/lang/Object;)Z");
+
+ jobject result = env->NewObject(set_class, set_ctr);
+
+ std::vector<OID> all_oids = get_all_curve_oids();
+
+ for (auto oid = all_oids.begin(); oid != all_oids.end(); ++oid) {
+ jstring name_str = env->NewStringUTF(oid_to_str(*oid).c_str());
+ env->CallBooleanMethod(result, set_add, name_str);
+ }
+
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported(JNIEnv *env, jobject self, jint keysize){
+ std::vector<OID> ecp_oids = get_curve_oids<ECP>();
+ for (auto oid = ecp_oids.begin(); oid != ecp_oids.end(); ++oid) {
+ DL_GroupParameters_EC<ECP> group(*oid);
+ if (((jint) group.GetCurve().GetField().MaxElementBitLength()) == keysize) {
+ return JNI_TRUE;
+ }
+ }
+
+ std::vector<OID> e2n_oids = get_curve_oids<EC2N>();
+ for (auto oid = e2n_oids.begin(); oid != e2n_oids.end(); ++oid) {
+ DL_GroupParameters_EC<EC2N> group(*oid);
+ if (((jint) group.GetCurve().FieldSize().ConvertToLong()) == keysize) {
+ return JNI_TRUE;
+ }
+ }
+ return JNI_FALSE;
+}
+
+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;
+ }
+
+ if (env->IsInstanceOf(params, ec_parameter_spec_class)) {
+ // Any custom params should be supported.
+ return JNI_TRUE;
+ } else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) {
+ // Compare with OIDs I guess?
+ jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (jstring) env->CallObjectMethod(params, get_name);
+ const char *utf_name = env->GetStringUTFChars(name, NULL);
+ std::string str_name(utf_name);
+ env->ReleaseStringUTFChars(name, utf_name);
+
+ std::vector<OID> all_oids = get_all_curve_oids();
+ for (auto oid = all_oids.begin(); oid != all_oids.end(); ++oid) {
+ std::string oid_s = oid_to_str(*oid);
+ if (str_name == oid_s) {
+ return JNI_TRUE;
+ }
+ }
+ }
+ return JNI_FALSE;
+}
+
+static Integer integer_from_biginteger(JNIEnv *env, jobject bigint) {
+ jmethodID to_byte_array = env->GetMethodID(biginteger_class, "toByteArray", "()[B");
+
+ jbyteArray byte_array = (jbyteArray) env->CallObjectMethod(bigint, to_byte_array);
+ jsize byte_length = env->GetArrayLength(byte_array);
+ jbyte *byte_data = env->GetByteArrayElements(byte_array, NULL);
+ Integer result((byte *) byte_data, (size_t) byte_length);
+ env->ReleaseByteArrayElements(byte_array, byte_data, JNI_ABORT);
+ return result;
+}
+
+static jobject biginteger_from_integer(JNIEnv *env, const Integer &integer) {
+ jbyteArray byte_array = (jbyteArray) env->NewByteArray(integer.MinEncodedSize());
+
+ jbyte *bigint_bytes = env->GetByteArrayElements(byte_array, NULL);
+ integer.Encode((byte *) bigint_bytes, integer.MinEncodedSize());
+ env->ReleaseByteArrayElements(byte_array, bigint_bytes, 0);
+
+ jmethodID biginteger_init = env->GetMethodID(biginteger_class, "<init>", "(I[B)V");
+ return env->NewObject(biginteger_class, biginteger_init, (jint) 1, byte_array);
+}
+
+static jobject biginteger_from_polmod2(JNIEnv *env, const PolynomialMod2 &polmod) {
+ jmethodID biginteger_init = env->GetMethodID(biginteger_class, "<init>", "(I[B)V");
+
+ jbyteArray mod_array = env->NewByteArray(polmod.MinEncodedSize());
+ jbyte *mod_data = env->GetByteArrayElements(mod_array, NULL);
+ polmod.Encode((byte *) mod_data, polmod.MinEncodedSize());
+ env->ReleaseByteArrayElements(mod_array, mod_data, 0);
+
+ return env->NewObject(biginteger_class, biginteger_init, (jint) 1, mod_array);
+}
+
+static std::unique_ptr<DL_GroupParameters_EC<ECP>> fp_group_from_params(JNIEnv *env, jobject params) {
+ if (env->IsInstanceOf(params, ec_parameter_spec_class)) {
+ jmethodID get_curve = env->GetMethodID(ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = env->CallObjectMethod(params, get_curve);
+
+ jmethodID get_field = env->GetMethodID(elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = env->CallObjectMethod(elliptic_curve, get_field);
+
+ if (!env->IsInstanceOf(field, fp_field_class)) {
+ return nullptr;
+ }
+
+ jmethodID get_a = env->GetMethodID(elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject a = env->CallObjectMethod(elliptic_curve, get_a);
+ Integer ai = integer_from_biginteger(env, a);
+
+ jmethodID get_b = env->GetMethodID(elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject b = env->CallObjectMethod(elliptic_curve, get_b);
+ Integer bi = integer_from_biginteger(env, b);
+
+ jmethodID get_g = env->GetMethodID(ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g = env->CallObjectMethod(params, get_g);
+
+ jmethodID get_x = env->GetMethodID(point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = env->CallObjectMethod(g, get_x);
+
+ jmethodID get_y = env->GetMethodID(point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = env->CallObjectMethod(g, get_y);
+
+ jmethodID get_n = env->GetMethodID(ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject n = env->CallObjectMethod(params, get_n);
+ Integer ni = integer_from_biginteger(env, n);
+
+ jmethodID get_h = env->GetMethodID(ec_parameter_spec_class, "getCofactor", "()I");
+ jint h = env->CallIntMethod(params, get_h);
+ Integer hi(h);
+
+ jmethodID get_p = env->GetMethodID(fp_field_class, "getP", "()Ljava/math/BigInteger;");
+ jobject p = env->CallObjectMethod(field, get_p);
+ Integer pi = integer_from_biginteger(env, p);
+
+ ECP curve(pi, ai, bi);
+
+ Integer gxi = integer_from_biginteger(env, gx);
+ Integer gyi = integer_from_biginteger(env, gy);
+ ECP::Point g_point(gxi, gyi);
+
+ return std::make_unique<DL_GroupParameters_EC<ECP>>(curve, g_point, ni, hi);
+ } else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (jstring) env->CallObjectMethod(params, get_name);
+ const char *utf_name = env->GetStringUTFChars(name, NULL);
+ std::string str_name(utf_name);
+ env->ReleaseStringUTFChars(name, utf_name);
+
+ std::vector<OID> ecp_oids = get_curve_oids<ECP>();
+ for (auto oid = ecp_oids.begin(); oid != ecp_oids.end(); ++oid) {
+ std::string oid_s = oid_to_str(*oid);
+ if (str_name == oid_s) {
+ return std::make_unique<DL_GroupParameters_EC<ECP>>(*oid);
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+static std::unique_ptr<DL_GroupParameters_EC<EC2N>> f2m_group_from_params(JNIEnv *env, jobject params) {
+ if (env->IsInstanceOf(params, ec_parameter_spec_class)) {
+ jmethodID get_curve = env->GetMethodID(ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = env->CallObjectMethod(params, get_curve);
+
+ jmethodID get_field = env->GetMethodID(elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = env->CallObjectMethod(elliptic_curve, get_field);
+
+ if (!env->IsInstanceOf(field, f2m_field_class)) {
+ return nullptr;
+ }
+
+ jmethodID get_a = env->GetMethodID(elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject a = env->CallObjectMethod(elliptic_curve, get_a);
+ Integer ai = integer_from_biginteger(env, a);
+
+ jmethodID get_b = env->GetMethodID(elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject b = env->CallObjectMethod(elliptic_curve, get_b);
+ Integer bi = integer_from_biginteger(env, b);
+
+ jmethodID get_g = env->GetMethodID(ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g = env->CallObjectMethod(params, get_g);
+
+ jmethodID get_x = env->GetMethodID(point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = env->CallObjectMethod(g, get_x);
+
+ jmethodID get_y = env->GetMethodID(point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = env->CallObjectMethod(g, get_y);
+
+ jmethodID get_n = env->GetMethodID(ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject n = env->CallObjectMethod(params, get_n);
+ Integer ni = integer_from_biginteger(env, n);
+
+ jmethodID get_h = env->GetMethodID(ec_parameter_spec_class, "getCofactor", "()I");
+ jint h = env->CallIntMethod(params, get_h);
+ Integer hi(h);
+
+ jmethodID get_midterms = env->GetMethodID(f2m_field_class, "getMidTermsOfReductionPolynomial", "()[I");
+ jintArray midterms = (jintArray) env->CallObjectMethod(field, get_midterms);
+ jsize midterm_length = env->GetArrayLength(midterms);
+ jint *midterm_data = env->GetIntArrayElements(midterms, NULL);
+
+ jmethodID get_m = env->GetMethodID(f2m_field_class, "getM", "()I");
+ jint m = env->CallIntMethod(field, get_m);
+
+ std::unique_ptr<GF2NP> base_field;
+ if (midterm_length == 1) {
+ //trinomial, use GF2NT
+ base_field = std::make_unique<GF2NT>((unsigned int) m, (unsigned int) midterm_data[0], 0);
+ } else {
+ //pentanomial, use GF2NPP
+ base_field = std::make_unique<GF2NPP>((unsigned int) m, (unsigned int) midterm_data[0], (unsigned int) midterm_data[1], (unsigned int) midterm_data[2], 0);
+ }
+ env->ReleaseIntArrayElements(midterms, midterm_data, JNI_ABORT);
+
+ jmethodID to_byte_array = env->GetMethodID(biginteger_class, "toByteArray", "()[B");
+ jbyteArray a_array = (jbyteArray) env->CallObjectMethod(a, to_byte_array);
+ jsize a_length = env->GetArrayLength(a_array);
+ jbyte *a_data = env->GetByteArrayElements(a_array, NULL);
+
+ jbyteArray b_array = (jbyteArray) env->CallObjectMethod(b, to_byte_array);
+ jsize b_length = env->GetArrayLength(b_array);
+ jbyte *b_data = env->GetByteArrayElements(b_array, NULL);
+
+ EC2N curve(*base_field, EC2N::FieldElement((byte *) a_data, (size_t) a_length), EC2N::FieldElement((byte *) b_data, (size_t) b_length));
+ env->ReleaseByteArrayElements(a_array, a_data, JNI_ABORT);
+ env->ReleaseByteArrayElements(b_array, b_data, JNI_ABORT);
+
+ jbyteArray gx_array = (jbyteArray) env->CallObjectMethod(gx, to_byte_array);
+ jsize gx_length = env->GetArrayLength(gx_array);
+ jbyte *gx_data = env->GetByteArrayElements(gx_array, NULL);
+ PolynomialMod2 gxm((byte *) gx_data, (size_t) gx_length);
+ env->ReleaseByteArrayElements(gx_array, gx_data, JNI_ABORT);
+
+ jbyteArray gy_array = (jbyteArray) env->CallObjectMethod(gy, to_byte_array);
+ jsize gy_length = env->GetArrayLength(gy_array);
+ jbyte *gy_data = env->GetByteArrayElements(gy_array, NULL);
+ PolynomialMod2 gym((byte *) gy_data, (size_t) gy_length);
+ env->ReleaseByteArrayElements(gy_array, gy_data, JNI_ABORT);
+
+ EC2N::Point g_point(gxm, gym);
+
+ return std::make_unique<DL_GroupParameters_EC<EC2N>>(curve, g_point, ni, hi);
+ } else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (jstring) env->CallObjectMethod(params, get_name);
+ const char *utf_name = env->GetStringUTFChars(name, NULL);
+ std::string str_name(utf_name);
+ env->ReleaseStringUTFChars(name, utf_name);
+
+ std::vector<OID> e2n_oids = get_curve_oids<EC2N>();
+ for (auto oid = e2n_oids.begin(); oid != e2n_oids.end(); ++oid) {
+ std::string oid_s = oid_to_str(*oid);
+ if (str_name == oid_s) {
+ return std::make_unique<DL_GroupParameters_EC<EC2N>>(*oid);
+ }
+ }
+ }
+ return nullptr;
+}
+
+
+template <class EC> jobject finish_params(JNIEnv *env, jobject field, jobject a, jobject b, jobject gx, jobject gy, DL_GroupParameters_EC<EC> group) {
+ jmethodID point_init = env->GetMethodID(point_class, "<init>", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject g = env->NewObject(point_class, point_init, gx, gy);
+
+ jmethodID elliptic_curve_init = env->GetMethodID(elliptic_curve_class, "<init>", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject elliptic_curve = env->NewObject(elliptic_curve_class, elliptic_curve_init, field, a, b);
+
+ // Integer GetSubgroupOrder
+ // Integer GetCofactor
+ jobject order = biginteger_from_integer(env, group.GetSubgroupOrder());
+ jint cofactor = (jint) group.GetCofactor().ConvertToLong();
+
+ jmethodID ec_parameter_spec_init = env->GetMethodID(ec_parameter_spec_class, "<init>", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V");
+ return env->NewObject(ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, order, cofactor);
+}
+
+template <class EC> jobject params_from_group(JNIEnv *env, DL_GroupParameters_EC<EC> group) {
+ return NULL;
+}
+
+template <> jobject params_from_group<ECP>(JNIEnv *env, DL_GroupParameters_EC<ECP> group) {
+ ECP curve = group.GetCurve();
+ jmethodID fp_field_init = env->GetMethodID(fp_field_class, "<init>", "(Ljava/math/BigInteger;)V");
+ ModularArithmetic mod = curve.GetField();
+ jobject p = biginteger_from_integer(env, mod.GetModulus());
+ jobject a = biginteger_from_integer(env, curve.GetA());
+ jobject b = biginteger_from_integer(env, curve.GetB());
+
+ jobject field = env->NewObject(fp_field_class, fp_field_init, p);
+
+ ECP::Point gp = group.GetBasePrecomputation().GetBase(group.GetGroupPrecomputation());
+ jobject gx = biginteger_from_integer(env, gp.x);
+ jobject gy = biginteger_from_integer(env, gp.y);
+ return finish_params(env, field, a, b, gx, gy, group);
+}
+
+template <> jobject params_from_group<EC2N>(JNIEnv *env, DL_GroupParameters_EC<EC2N> group) {
+ EC2N curve = group.GetCurve();
+ PolynomialMod2 mod = curve.GetField().GetModulus();
+ int m = mod.Degree();
+ unsigned int coeff_count = mod.CoefficientCount();
+ jintArray ks;
+ int to_find;
+ int found = 0;
+ if (coeff_count == 3) {
+ //trinomial
+ ks = env->NewIntArray(1);
+ to_find = 1;
+ } else if (coeff_count == 5) {
+ //pentanomial
+ ks = env->NewIntArray(3);
+ to_find = 3;
+ }
+ jint *ks_data = env->GetIntArrayElements(ks, NULL);
+ for (int i = m - 1; i > 0 && found < to_find; --i) {
+ if (mod.GetCoefficient(i) == 1) {
+ ks_data[found++] = i;
+ }
+ }
+ env->ReleaseIntArrayElements(ks, ks_data, 0);
+
+ jmethodID f2m_field_init = env->GetMethodID(f2m_field_class, "<init>", "(I[I)V");
+ jobject field = env->NewObject(f2m_field_class, f2m_field_init, (jint) m, ks);
+
+ jobject a = biginteger_from_polmod2(env, curve.GetA());
+ jobject b = biginteger_from_polmod2(env, curve.GetB());
+
+ EC2N::Point gp = group.GetBasePrecomputation().GetBase(group.GetGroupPrecomputation());
+ jobject gx = biginteger_from_polmod2(env, gp.x);
+ jobject gy = biginteger_from_polmod2(env, gp.y);
+ return finish_params(env, field, a, b, gx, gy, group);
+}
+
+template <class EC> jobject generate_from_group(JNIEnv *env, DL_GroupParameters_EC<EC> group, jobject params) {
+ AutoSeededRandomPool rng;
+ typename ECDH<EC>::Domain ec_domain(group);
+ SecByteBlock priv(ec_domain.PrivateKeyLength()), pub(ec_domain.PublicKeyLength());
+
+ try {
+ ec_domain.GenerateKeyPair(rng, priv, pub);
+ } catch (Exception & ex) {
+ throw_new(env, "java/security/GeneralSecurityException", ex.what());
+ return NULL;
+ }
+
+ jbyteArray pub_bytearray = env->NewByteArray(pub.SizeInBytes());
+ jbyte *pub_bytes = env->GetByteArrayElements(pub_bytearray, NULL);
+ std::copy(pub.BytePtr(), pub.BytePtr()+pub.SizeInBytes(), pub_bytes);
+ env->ReleaseByteArrayElements(pub_bytearray, pub_bytes, 0);
+
+ jobject ec_pub_param_spec = env->NewLocalRef(params);
+ jmethodID ec_pub_init = env->GetMethodID(pubkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject pubkey = env->NewObject(pubkey_class, ec_pub_init, pub_bytearray, ec_pub_param_spec);
+
+ jbyteArray priv_bytearray = env->NewByteArray(priv.SizeInBytes());
+ jbyte *priv_bytes = env->GetByteArrayElements(priv_bytearray, NULL);
+ std::copy(priv.BytePtr(), priv.BytePtr()+priv.SizeInBytes(), priv_bytes);
+ env->ReleaseByteArrayElements(priv_bytearray, priv_bytes, 0);
+
+ jobject ec_priv_param_spec = env->NewLocalRef(params);
+ jmethodID ec_priv_init = env->GetMethodID(privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject privkey = env->NewObject(privkey_class, ec_priv_init, priv_bytearray, ec_priv_param_spec);
+
+ jmethodID keypair_init = env->GetMethodID(keypair_class, "<init>", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+
+ return env->NewObject(keypair_class, keypair_init, pubkey, privkey);
+}
+
+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<OID> ecp_oids = get_curve_oids<ECP>();
+ for (auto oid = ecp_oids.begin(); oid != ecp_oids.end(); ++oid) {
+ DL_GroupParameters_EC<ECP> group(*oid);
+ if (((jint) group.GetCurve().GetField().MaxElementBitLength()) == keysize) {
+ jobject params = params_from_group(env, group);
+ return generate_from_group<ECP>(env, group, params);
+ }
+ }
+
+ std::vector<OID> e2n_oids = get_curve_oids<EC2N>();
+ for (auto oid = e2n_oids.begin(); oid != e2n_oids.end(); ++oid) {
+ DL_GroupParameters_EC<EC2N> group(*oid);
+ if ((jint) group.GetCurve().FieldSize().ConvertToLong() == keysize) {
+ jobject params = params_from_group(env, group);
+ return generate_from_group<EC2N>(env, group, params);
+ }
+ }
+ return NULL;
+}
+
+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<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params);
+ if (ecp_group == nullptr) {
+ std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params);
+ return generate_from_group<EC2N>(env, *ec2n_group, params);
+ } else {
+ return generate_from_group<ECP>(env, *ecp_group, params);
+ }
+ return NULL;
+}
+
+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);
+ SecByteBlock private_key((byte *) privkey_data, privkey_length);
+ env->ReleaseByteArrayElements(privkey, privkey_data, JNI_ABORT);
+
+ jsize pubkey_length = env->GetArrayLength(pubkey);
+ jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL);
+ SecByteBlock public_key((byte *) pubkey_data, pubkey_length);
+ env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT);
+
+ bool success;
+ std::unique_ptr<SecByteBlock> secret;
+ std::unique_ptr<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params);
+ if (ecp_group == nullptr) {
+ std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params);
+ ECDH<EC2N>::Domain dh_agreement(*ec2n_group);
+
+ try {
+ secret = std::make_unique<SecByteBlock>(dh_agreement.AgreedValueLength());
+ success = dh_agreement.Agree(*secret, private_key, public_key);
+ } catch (Exception & ex) {
+ throw_new(env, "java/security/GeneralSecurityException", ex.what());
+ return NULL;
+ }
+ } else {
+ ECDH<ECP>::Domain dh_agreement(*ecp_group);
+
+ try {
+ secret = std::make_unique<SecByteBlock>(dh_agreement.AgreedValueLength());
+ success = dh_agreement.Agree(*secret, private_key, public_key);
+ } catch (Exception & ex) {
+ throw_new(env, "java/security/GeneralSecurityException", ex.what());
+ return NULL;
+ }
+ }
+
+ jbyteArray result = env->NewByteArray(secret->size());
+ jbyte *result_data = env->GetByteArrayElements(result, NULL);
+ std::copy(secret->begin(), secret->end(), result_data);
+ env->ReleaseByteArrayElements(result, result_data, 0);
+
+ return result;
+}
+
+template <class EC, class H>
+jbyteArray sign_message(JNIEnv *env, DL_GroupParameters_EC<EC> group, jbyteArray data, const Integer & private_key_x) {
+ AutoSeededRandomPool prng;
+
+ typename ECDSA<EC, H>::PrivateKey pkey;
+ pkey.Initialize(group, private_key_x);
+ typename ECDSA<EC, H>::Signer signer(pkey);
+
+ std::string signature(signer.MaxSignatureLength(), 0);
+
+ jsize data_length = env->GetArrayLength(data);
+ jbyte *data_bytes = env->GetByteArrayElements(data, NULL);
+ size_t len = signer.SignMessage(prng, (byte *)data_bytes, data_length, (byte *)signature.c_str());
+ env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
+ signature.resize(len);
+
+ jbyteArray result = env->NewByteArray(len);
+ jbyte *result_bytes = env->GetByteArrayElements(result, NULL);
+ std::copy(signature.begin(), signature.end(), result_bytes);
+ env->ReleaseByteArrayElements(result, result_bytes, 0);
+
+ return result;
+}
+
+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;");
+ jstring type = (jstring) env->GetObjectField(self, type_id);
+ const char *type_data = env->GetStringUTFChars(type, NULL);
+ std::string type_str(type_data);
+ env->ReleaseStringUTFChars(type, type_data);
+
+ jsize privkey_length = env->GetArrayLength(privkey);
+ jbyte *privkey_data = env->GetByteArrayElements(privkey, NULL);
+ Integer private_key_x((byte *) privkey_data, (size_t) privkey_length);
+ env->ReleaseByteArrayElements(privkey, privkey_data, JNI_ABORT);
+
+ jbyteArray result;
+
+ std::unique_ptr<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params);
+ if (ecp_group == nullptr) {
+ std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params);
+ if (type_str.find("SHA1") != std::string::npos) {
+ result = sign_message<EC2N, SHA1>(env, *ec2n_group, data, private_key_x);
+ } else if (type_str.find("SHA224") != std::string::npos) {
+ result = sign_message<EC2N, SHA224>(env, *ec2n_group, data, private_key_x);
+ } else if (type_str.find("SHA256") != std::string::npos) {
+ result = sign_message<EC2N, SHA256>(env, *ec2n_group, data, private_key_x);
+ } else if (type_str.find("SHA384") != std::string::npos) {
+ result = sign_message<EC2N, SHA384>(env, *ec2n_group, data, private_key_x);
+ } else if (type_str.find("SHA512") != std::string::npos) {
+ result = sign_message<EC2N, SHA512>(env, *ec2n_group, data, private_key_x);
+ }
+ } else {
+ if (type_str.find("SHA1") != std::string::npos) {
+ result = sign_message<ECP, SHA1>(env, *ecp_group, data, private_key_x);
+ } else if (type_str.find("SHA224") != std::string::npos) {
+ result = sign_message<ECP, SHA224>(env, *ecp_group, data, private_key_x);
+ } else if (type_str.find("SHA256") != std::string::npos) {
+ result = sign_message<ECP, SHA256>(env, *ecp_group, data, private_key_x);
+ } else if (type_str.find("SHA384") != std::string::npos) {
+ result = sign_message<ECP, SHA384>(env, *ecp_group, data, private_key_x);
+ } else if (type_str.find("SHA512") != std::string::npos) {
+ result = sign_message<ECP, SHA512>(env, *ecp_group, data, private_key_x);
+ }
+ }
+
+ return result;
+}
+
+template <class EC, class H>
+jboolean verify_message(JNIEnv *env, DL_GroupParameters_EC<EC> group, jbyteArray data, jbyteArray signature, jbyteArray pubkey) {
+ typename EC::Point pkey_point;
+ jsize pubkey_length = env->GetArrayLength(pubkey);
+ jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL);
+ group.GetCurve().DecodePoint(pkey_point, (byte *)pubkey_data, pubkey_length);
+ env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT);
+
+ typename ECDSA<EC, H>::PublicKey pkey;
+ pkey.Initialize(group, pkey_point);
+ typename ECDSA<EC, H>::Verifier verifier(pkey);
+
+ jsize data_length = env->GetArrayLength(data);
+ jbyte *data_bytes = env->GetByteArrayElements(data, NULL);
+ jsize sig_length = env->GetArrayLength(signature);
+ jbyte *sig_bytes = env->GetByteArrayElements(signature, NULL);
+ bool result = verifier.VerifyMessage((byte *)data_bytes, data_length, (byte *)sig_bytes, sig_length);
+ env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
+ env->ReleaseByteArrayElements(signature, sig_bytes, JNI_ABORT);
+
+ return result;
+}
+
+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;");
+ jstring type = (jstring) env->GetObjectField(self, type_id);
+ const char *type_data = env->GetStringUTFChars(type, NULL);
+ std::string type_str(type_data);
+ env->ReleaseStringUTFChars(type, type_data);
+
+ std::unique_ptr<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params);
+ if (ecp_group == nullptr) {
+ std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params);
+
+ if (type_str.find("SHA1") != std::string::npos) {
+ return verify_message<EC2N, SHA1>(env, *ec2n_group, data, signature, pubkey);
+ } else if (type_str.find("SHA224") != std::string::npos) {
+ return verify_message<EC2N, SHA224>(env, *ec2n_group, data, signature, pubkey);
+ } else if (type_str.find("SHA256") != std::string::npos) {
+ return verify_message<EC2N, SHA256>(env, *ec2n_group, data, signature, pubkey);
+ } else if (type_str.find("SHA384") != std::string::npos) {
+ return verify_message<EC2N, SHA384>(env, *ec2n_group, data, signature, pubkey);
+ } else if (type_str.find("SHA512") != std::string::npos) {
+ return verify_message<EC2N, SHA512>(env, *ec2n_group, data, signature, pubkey);
+ }
+ } else {
+ if (type_str.find("SHA1") != std::string::npos) {
+ return verify_message<ECP, SHA1>(env, *ecp_group, data, signature, pubkey);
+ } else if (type_str.find("SHA224") != std::string::npos) {
+ return verify_message<ECP, SHA224>(env, *ecp_group, data, signature, pubkey);
+ } else if (type_str.find("SHA256") != std::string::npos) {
+ return verify_message<ECP, SHA256>(env, *ecp_group, data, signature, pubkey);
+ } else if (type_str.find("SHA384") != std::string::npos) {
+ return verify_message<ECP, SHA384>(env, *ecp_group, data, signature, pubkey);
+ } else if (type_str.find("SHA512") != std::string::npos) {
+ return verify_message<ECP, SHA512>(env, *ecp_group, data, signature, pubkey);
+ }
+ }
+ // unreachable
+ return JNI_FALSE;
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c
new file mode 100644
index 0000000..16736d7
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c
@@ -0,0 +1,1210 @@
+#include "native.h"
+#include <windows.h>
+#include <bcrypt.h>
+
+#include "c_utils.h"
+
+#include <stdio.h>
+
+
+
+// BCRYPT and NT things.
+#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0)
+#define NT_FAILURE(status) !NT_SUCCESS(status)
+
+#define STATUS_SUCCESS 0x00000000
+#define STATUS_INVALID_SIGNATURE 0xC000A000
+
+typedef struct {
+ ULONG dwVersion; //Version of the structure
+ ECC_CURVE_TYPE_ENUM dwCurveType; //Supported curve types.
+ ECC_CURVE_ALG_ID_ENUM dwCurveGenerationAlgId; //For X.592 verification purposes, if we include Seed we will need to include the algorithm ID.
+ ULONG cbFieldLength; //Byte length of the fields P, A, B, X, Y.
+ ULONG cbSubgroupOrder; //Byte length of the subgroup.
+ ULONG cbCofactor; //Byte length of cofactor of G in E.
+ ULONG cbSeed; //Byte length of the seed used to generate the curve.
+} BCRYPT_ECC_PARAMETER_HEADER;
+
+//Provider things
+static jclass provider_class;
+
+#define KEYFLAG_IMPLICIT 0 //Mscng native key, over named curve
+#define KEYFLAG_EXPLICIT 1 //Mscng native key, over explicit ecc parameters
+#define KEYFLAG_NIST 2 //Mscng native key, over NIST parameters, custom ECDH/ECDSA_P* algo
+#define KEYFLAG_OTHER 3 //Other key, explicit ecc parameters
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self) {
+ jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng");
+ provider_class = (*env)->NewGlobalRef(env, local_provider_class);
+
+ jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V");
+
+ jstring name = (*env)->NewStringUTF(env, "Microsoft CNG");
+ double version = 1.0;
+
+ return (*env)->NewObject(env, provider_class, init, name, version, name);
+}
+
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup(JNIEnv *env, jobject self) {
+ INIT_PROVIDER(env, provider_class);
+
+ ADD_KPG(env, self, "ECDH", "MscngECDH");
+ ADD_KPG(env, self, "ECDSA", "MscngECDSA");
+
+ ADD_KA(env, self, "ECDHwithSHA1KDF", "MscngECDHwithSHA1KDF");
+ ADD_KA(env, self, "ECDHwithSHA256KDF", "MscngECDHwithSHA256KDF");
+ ADD_KA(env, self, "ECDHwithSHA384KDF", "MscngECDHwithSHA384KDF");
+ ADD_KA(env, self, "ECDHwithSHA512KDF", "MscngECDHwithSHA512KDF");
+
+ ADD_SIG(env, self, "SHA1withECDSA", "MscngECDSAwithSHA1");
+ ADD_SIG(env, self, "SHA256withECDSA", "MscngECDSAwithSHA256");
+ ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384");
+ ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112");
+
+ init_classes(env, "Mscng");
+}
+
+typedef struct {
+ LPCSTR name;
+ ULONG bits;
+} named_curve_t;
+
+static named_curve_t named_curves[] = {
+ {"curve25519", 256},
+ {"brainpoolP160r1", 160},
+ {"brainpoolP160t1", 160},
+ {"brainpoolP192r1", 192},
+ {"brainpoolP192t1", 192},
+ {"brainpoolP224r1", 224},
+ {"brainpoolP224t1", 224},
+ {"brainpoolP256r1", 256},
+ {"brainpoolP256t1", 256},
+ {"brainpoolP320r1", 320},
+ {"brainpoolP320t1", 320},
+ {"brainpoolP384r1", 384},
+ {"brainpoolP384t1", 384},
+ {"brainpoolP512r1", 512},
+ {"brainpoolP512t1", 512},
+ {"ec192wapi", 192},
+ {"nistP192", 192},
+ {"nistP224", 224},
+ {"nistP256", 256},
+ {"nistP384", 384},
+ {"nistP521", 521},
+ {"numsP256t1", 256},
+ {"numsP384t1", 384},
+ {"numsP512t1", 512},
+ {"secP160k1", 160},
+ {"secP160r1", 160},
+ {"secP160r2", 160},
+ {"secP192k1", 192},
+ {"secP192r1", 192},
+ {"secP224k1", 224},
+ {"secP224r1", 224},
+ {"secP256k1", 256},
+ {"secP256r1", 256},
+ {"secP384r1", 384},
+ {"secP521r1", 521},
+ {"wtls12", 224},
+ {"wtls7", 160},
+ {"wtls9", 160},
+ {"x962P192v1", 192},
+ {"x962P192v2", 192},
+ {"x962P192v3", 192},
+ {"x962P239v1", 239},
+ {"x962P239v2", 239},
+ {"x962P239v3", 239},
+ {"x962P256v1", 256}
+};
+
+static const named_curve_t* lookup_curve(const char *name) {
+ for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) {
+ if (strcmp(name, named_curves[i].name) == 0) {
+ 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 NWPSTR null-terminated.
+ * Returns: Length of NWPSTR 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");
+
+ jmethodID hash_set_ctr = (*env)->GetMethodID(env, hash_set_class, "<init>", "()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);
+
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE handle;
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, BCRYPT_ECDH_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ return result;
+ }
+
+ ULONG bufSize;
+ if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptGetProperty(length only)\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return result;
+ }
+
+ 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))) {
+ wprintf(L"**** Error 0x%x returned by BCryptGetProperty(whole)\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ free(curves);
+ return result;
+ }
+
+ 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) {
+ 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) {
+ if (params == NULL) {
+ return JNI_FALSE;
+ }
+
+ 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);
+ const named_curve_t *curve = lookup_curve(utf_name);
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ return curve == NULL ? JNI_FALSE : JNI_TRUE;
+ } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject 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, curve, get_field);
+
+ if ((*env)->IsInstanceOf(env, field, fp_field_class)) {
+ return JNI_TRUE;
+ } else {
+ return JNI_FALSE;
+ }
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jobject bytes_to_biginteger(JNIEnv *env, PBYTE bytes, int len) {
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "<init>", "(I[B)V");
+ jbyteArray byte_array = (*env)->NewByteArray(env, len);
+ jbyte *data = (*env)->GetByteArrayElements(env, byte_array, NULL);
+ memcpy(data, bytes, len);
+ (*env)->ReleaseByteArrayElements(env, byte_array, data, 0);
+ jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, byte_array);
+ return result;
+}
+
+static void biginteger_to_bytes(JNIEnv *env, jobject bigint, PBYTE bytes, ULONG len) {
+ 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);
+ memcpy(bytes, &byte_data[byte_length - len], len);
+ (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT);
+}
+
+static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLength) {
+ //
+ // 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;
+ PBYTE A = P + header->cbFieldLength;
+ PBYTE B = A + header->cbFieldLength;
+ PBYTE GX = B + header->cbFieldLength;
+ PBYTE GY = GX + header->cbFieldLength;
+
+ //cbSubgroupOrder
+ PBYTE N = GY + header->cbFieldLength;
+
+ //cbCofactor
+ PBYTE H = N + header->cbSubgroupOrder;
+
+ //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, "<init>", "(Ljava/math/BigInteger;)V");
+ jobject field = (*env)->NewObject(env, fp_field_class, fp_field_init, p_int);
+
+ jobject a_int = bytes_to_biginteger(env, A, header->cbFieldLength);
+ jobject b_int = bytes_to_biginteger(env, B, header->cbFieldLength);
+
+ jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "<init>", "(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);
+
+ jobject gx_int = bytes_to_biginteger(env, GX, header->cbFieldLength);
+ jobject gy_int = bytes_to_biginteger(env, GY, header->cbFieldLength);
+
+ jmethodID point_init = (*env)->GetMethodID(env, point_class, "<init>", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int);
+
+ jobject n_int = bytes_to_biginteger(env, N, header->cbSubgroupOrder);
+
+ jobject h_int = bytes_to_biginteger(env, H, header->cbCofactor);
+ jmethodID bigint_to_int = (*env)->GetMethodID(env, biginteger_class, "intValue", "()I");
+ jint cof = (*env)->CallIntMethod(env, h_int, bigint_to_int);
+
+ jmethodID ec_parameter_spec_init = (*env)->GetMethodID(env, ec_parameter_spec_class, "<init>", "(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, n_int, cof);
+}
+
+static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) {
+ 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);
+
+ jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b);
+
+ jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;");
+ jobject p = (*env)->CallObjectMethod(env, field, get_p);
+
+ 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);
+
+ jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = (*env)->CallObjectMethod(env, g, get_y);
+
+ jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject n = (*env)->CallObjectMethod(env, params, get_n);
+
+ jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I");
+ jint h = (*env)->CallIntMethod(env, params, get_h);
+
+ jmethodID get_bitlength = (*env)->GetMethodID(env, biginteger_class, "bitLength", "()I");
+ jint order_bits = (*env)->CallIntMethod(env, n, get_bitlength);
+ 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 + 1 + 0;
+ *curve = calloc(bufSize, 1);
+ BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve;
+ header->dwVersion = 1;
+ header->dwCurveType = 1; //1 -> Prime short Weierstrass, 2 -> Prime Twisted Edwards, 3 -> Montgomery
+ header->dwCurveGenerationAlgId = 0;
+ header->cbFieldLength = bytes;
+ header->cbSubgroupOrder = order_bytes;
+ header->cbCofactor = 1;
+ header->cbSeed = 0;
+
+ PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)];
+
+ biginteger_to_bytes(env, p, paramsStart, bytes);
+ biginteger_to_bytes(env, a, paramsStart + bytes, bytes);
+ biginteger_to_bytes(env, b, paramsStart + 2 * bytes, bytes);
+ 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);
+ 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, jint *keyflag, NWPSTR *curve_name, LPCWSTR algo, jobject params) {
+ NTSTATUS status;
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ return 0;
+ }
+ ULONG result = 0;
+ 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);
+ jint utf_length = (*env)->GetStringUTFLength(env, name);
+ PUCHAR chars = calloc(utf_length + 1, 1);
+ (*env)->GetStringUTFRegion(env, name, 0, utf_length, chars);
+ const named_curve_t *curve = lookup_curve(chars);
+ ULONG ret = utf_8to16(curve_name, chars);
+ if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, (PUCHAR)*curve_name, ret * sizeof(WCHAR), 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status);
+ return 0;
+ }
+ free(chars);
+ result = curve->bits;
+ *keyflag = KEYFLAG_IMPLICIT;
+ } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ PBYTE curve;
+ ULONG curveLen = create_curve(env, params, &curve);
+ if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status);
+ return 0;
+ }
+ free(curve);
+
+ 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);
+ result = bits;
+ *keyflag = KEYFLAG_EXPLICIT;
+ *curve_name = NULL;
+ }
+ return result;
+}
+
+static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPCWSTR curve) {
+ NTSTATUS status;
+ ULONG bufSize = 0;
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status);
+ return NULL;
+ }
+ if (bufSize == 0) {
+ printf("buf 0\n");
+ return NULL;
+ }
+
+ PBYTE fullBuf = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, fullBuf, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status);
+ free(fullBuf);
+ return NULL;
+ }
+
+ ULONG paramLength;
+ jobject ec_priv_param_spec = create_ec_param_spec(env, fullBuf, &paramLength);
+
+ // fullBuf looks like:
+ // 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.
+ // Qx[cbFieldLength] X-coordinate of the public point.
+ // Qy[cbFieldLength] Y-coordinate of the public point.
+ // d[cbSubgroupOrder] Private key.
+ BCRYPT_ECCFULLKEY_BLOB *privHeader = (BCRYPT_ECCFULLKEY_BLOB*)fullBuf;
+ PBYTE priv_x = &fullBuf[paramLength];
+ PBYTE priv_y = priv_x + privHeader->cbFieldLength;
+ PBYTE priv = priv_y + privHeader->cbFieldLength;
+
+
+ jbyteArray meta_bytes = NULL;
+ jbyteArray header_bytes = NULL;
+ switch (flag) {
+ case 0: {
+ // meta = curve
+ jint meta_len = (wcslen(curve) + 1) * sizeof(WCHAR);
+ meta_bytes = (*env)->NewByteArray(env, meta_len);
+ jbyte *meta_data = (*env)->GetByteArrayElements(env, meta_bytes, NULL);
+ memcpy(meta_data, curve, meta_len);
+ (*env)->ReleaseByteArrayElements(env, meta_bytes, meta_data, 0);
+ }
+ case 1:
+ case 2: {
+ // meta = null
+ // header = full
+ header_bytes = (*env)->NewByteArray(env, paramLength);
+ jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL);
+ memcpy(header_data, fullBuf, paramLength);
+ (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0);
+ break;
+ }
+ default:
+ // header = small
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, length only)\n", status);
+ free(fullBuf);
+ return NULL;
+ }
+ if (bufSize == 0) {
+ printf("buf 0\n");
+ free(fullBuf);
+ return NULL;
+ }
+ PBYTE smallBuf = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, smallBuf, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, whole)\n", status);
+ free(fullBuf);
+ free(smallBuf);
+ return NULL;
+ }
+ // smallBuf looks like:
+ // BCRYPT_ECCKEY_BLOB header
+ // Qx[cbFieldLength] X-coordinate of the public point.
+ // Qy[cbFieldLength] Y-coordinate of the public point.
+ // d[cbSubgroupOrder] Private key.
+ header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB));
+ jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL);
+ memcpy(header_data, smallBuf, sizeof(BCRYPT_ECCKEY_BLOB));
+ (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0);
+ free(smallBuf);
+ break;
+ }
+
+ jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength);
+ jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL);
+ memcpy(x_data, priv_x, privHeader->cbFieldLength);
+ (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0);
+
+ jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength);
+ jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL);
+ memcpy(y_data, priv_y, privHeader->cbFieldLength);
+ (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0);
+
+ jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbSubgroupOrder);
+ jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
+ memcpy(key_priv, priv, privHeader->cbSubgroupOrder);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
+
+ free(fullBuf);
+
+ jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "<init>", "(I[B[B[B[B[BLjava/security/spec/ECParameterSpec;)V");
+ return (*env)->NewObject(env, privkey_class, ec_priv_init, flag, meta_bytes, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec);
+}
+
+static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPCWSTR curve) {
+ NTSTATUS status;
+ ULONG bufSize = 0;
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status);
+ return NULL;
+ }
+ if (bufSize == 0) {
+ printf("err0\n");
+ return NULL;
+ }
+
+ PBYTE fullBuf = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, fullBuf, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status);
+ return NULL;
+ }
+
+ ULONG paramLength;
+ jobject ec_pub_param_spec = create_ec_param_spec(env, fullBuf, &paramLength);
+
+ // fullBuf looks like:
+ // 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.
+ // Qx[cbFieldLength] X-coordinate of the public point.
+ // Qy[cbFieldLength] Y-coordinate of the public point.
+ BCRYPT_ECCFULLKEY_BLOB *pubHeader = (BCRYPT_ECCFULLKEY_BLOB*)fullBuf;
+ PBYTE pub_x = &fullBuf[paramLength];
+ PBYTE pub_y = pub_x + pubHeader->cbFieldLength;
+
+ jbyteArray meta_bytes = NULL;
+ jbyteArray header_bytes = NULL;
+ switch (flag) {
+ case 0: {
+ // meta = curve
+ jint meta_len = (wcslen(curve) + 1) * sizeof(WCHAR);
+ meta_bytes = (*env)->NewByteArray(env, meta_len);
+ jbyte *meta_data = (*env)->GetByteArrayElements(env, meta_bytes, NULL);
+ memcpy(meta_data, curve, meta_len);
+ (*env)->ReleaseByteArrayElements(env, meta_bytes, meta_data, 0);
+ }
+ case 1:
+ case 2: {
+ header_bytes = (*env)->NewByteArray(env, paramLength);
+ jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL);
+ memcpy(header_data, pubHeader, paramLength);
+ (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0);
+ break;
+ }
+ default:
+ // header = small
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, length only)\n", status);
+ free(fullBuf);
+ return NULL;
+ }
+ if (bufSize == 0) {
+ printf("buf 0\n");
+ free(fullBuf);
+ return NULL;
+ }
+ PBYTE smallBuf = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, smallBuf, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, whole)\n", status);
+ free(fullBuf);
+ free(smallBuf);
+ return NULL;
+ }
+ // smallBuf looks like:
+ // BCRYPT_ECCKEY_BLOB header
+ // Qx[cbFieldLength] X-coordinate of the public point.
+ // Qy[cbFieldLength] Y-coordinate of the public point.
+ header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB));
+ jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL);
+ memcpy(header_data, smallBuf, sizeof(BCRYPT_ECCKEY_BLOB));
+ (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0);
+ free(smallBuf);
+ break;
+ }
+
+ jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength);
+ jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL);
+ memcpy(x_data, pub_x, pubHeader->cbFieldLength);
+ (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0);
+
+ jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength);
+ jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL);
+ memcpy(y_data, pub_y, pubHeader->cbFieldLength);
+ (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0);
+
+ free(fullBuf);
+
+ jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "<init>", "(I[B[B[B[BLjava/security/spec/ECParameterSpec;)V");
+ return (*env)->NewObject(env, pubkey_class, ec_pub_init, flag, meta_bytes, 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) {
+ 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:
+ //unreachable
+ return NULL;
+ }
+ } 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:
+ //unreachable
+ return NULL;
+ }
+ } else {
+ //unreachable
+ return NULL;
+ }
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, algo, MS_PRIMITIVE_PROVIDER, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider", status);
+ return NULL;
+ }
+
+ BCRYPT_KEY_HANDLE key = NULL;
+
+ if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, keysize, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGenerateKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return NULL;
+ }
+
+ if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptFinalizeKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return NULL;
+ }
+
+ jobject privkey = key_to_privkey(env, key, KEYFLAG_NIST, NULL);
+ jobject pubkey = key_to_pubkey(env, key, KEYFLAG_NIST, NULL);
+
+ jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "<init>", "(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) {
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE handle = NULL;
+ BCRYPT_KEY_HANDLE key = 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) {
+ algo = BCRYPT_ECDH_ALGORITHM;
+ } else if (strcmp(type_data, "ECDSA") == 0) {
+ algo = BCRYPT_ECDSA_ALGORITHM;
+ } else {
+ //unreachable
+ return NULL;
+ }
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+
+ jint keyflag;
+ NWPSTR curveName;
+ ULONG bits = init_algo(env, &handle, &keyflag, &curveName, algo, params);
+ if (bits == 0) {
+ throw_new(env, "java/security/GeneralSecurityException", "Couldn't initialize algo.");
+ return NULL;
+ }
+
+ if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, bits, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGenerateKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return NULL;
+ }
+
+ if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptFinalizeKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return NULL;
+ }
+
+ jobject privkey = key_to_privkey(env, key, keyflag, curveName);
+ jobject pubkey = key_to_pubkey(env, key, keyflag, curveName);
+
+ if (curveName) {
+ free(curveName);
+ }
+
+ jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "<init>", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+
+ BCryptDestroyKey(key);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey);
+}
+
+static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR type, jint keyflag, jbyteArray meta, jobject params) {
+ LPCWSTR ecdh_algos[] = {
+ BCRYPT_ECDH_ALGORITHM,
+ BCRYPT_ECDH_P256_ALGORITHM,
+ BCRYPT_ECDH_P384_ALGORITHM,
+ BCRYPT_ECDH_P521_ALGORITHM
+ };
+ LPCWSTR ecdsa_algos[] = {
+ BCRYPT_ECDSA_ALGORITHM,
+ BCRYPT_ECDSA_P256_ALGORITHM,
+ BCRYPT_ECDSA_P384_ALGORITHM,
+ BCRYPT_ECDSA_P521_ALGORITHM
+ };
+
+ LPCWSTR *algos;
+ LPCWSTR algo;
+ if (lstrcmpW(type, BCRYPT_ECDH_ALGORITHM) == 0) {
+ algos = ecdh_algos;
+ } else if (lstrcmpW(type, BCRYPT_ECDSA_ALGORITHM) == 0) {
+ algos = ecdsa_algos;
+ } else {
+ //unreachable
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (keyflag) {
+ case KEYFLAG_IMPLICIT:
+ case KEYFLAG_EXPLICIT:
+ case KEYFLAG_OTHER:
+ algo = algos[0];
+ break;
+ case KEYFLAG_NIST: {
+ 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);
+ switch (bits) {
+ case 256:
+ algo = algos[1];
+ break;
+ case 384:
+ algo = algos[2];
+ break;
+ case 521:
+ algo = algos[3];
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
+ }
+ NTSTATUS status;
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ return status;
+ }
+
+ switch (keyflag) {
+ case KEYFLAG_IMPLICIT: {
+ jint meta_len = (*env)->GetArrayLength(env, meta);
+ jbyte *meta_data = (*env)->GetByteArrayElements(env, meta, NULL);
+ //if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, meta_data, meta_len, 0))) {
+ // throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSetProperty(curve name)\n", status);
+ // (*env)->ReleaseByteArrayElements(env, meta, meta_data, JNI_ABORT);
+ // return status;
+ //}
+ (*env)->ReleaseByteArrayElements(env, meta, meta_data, JNI_ABORT);
+ break;
+ }
+ case KEYFLAG_EXPLICIT:
+ case KEYFLAG_OTHER: {
+ PBYTE curve;
+ ULONG curve_len = create_curve(env, params, &curve);
+ if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curve_len, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSetProperty(parameters)\n", status);
+ free(curve);
+ return status;
+ }
+ free(curve);
+ break;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+static jint get_keyflag(JNIEnv *env, jobject key) {
+ if ((*env)->IsInstanceOf(env, key, pubkey_class) || (*env)->IsInstanceOf(env, key, privkey_class)) {
+ jclass key_class = (*env)->GetObjectClass(env, key);
+ jmethodID get_flag = (*env)->GetMethodID(env, key_class, "getFlag", "()I");
+ return (*env)->CallIntMethod(env, key, get_flag);
+ } else {
+ return KEYFLAG_OTHER;
+ }
+}
+
+static jbyteArray get_meta(JNIEnv *env, jobject key) {
+ if ((*env)->IsInstanceOf(env, key, pubkey_class) || (*env)->IsInstanceOf(env, key, privkey_class)) {
+ jclass key_class = (*env)->GetObjectClass(env, key);
+ jmethodID get_meta = (*env)->GetMethodID(env, key_class, "getMeta", "()[B");
+ return (jbyteArray)(*env)->CallObjectMethod(env, key, get_meta);
+ } else {
+ return NULL;
+ }
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jobject pubkey, jobject privkey, jobject params) {
+ NTSTATUS status;
+
+ 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);
+ const char* type_data = (*env)->GetStringUTFChars(env, type, NULL);
+ LPCWSTR kdf_algo;
+ if (strcmp(type_data, "ECDHwithSHA1KDF") == 0) {
+ kdf_algo = BCRYPT_SHA1_ALGORITHM;
+ } else if (strcmp(type_data, "ECDHwithSHA256KDF") == 0) {
+ kdf_algo = BCRYPT_SHA256_ALGORITHM;
+ } else if (strcmp(type_data, "ECDHwithSHA384KDF") == 0) {
+ kdf_algo = BCRYPT_SHA384_ALGORITHM;
+ } else if (strcmp(type_data, "ECDHwithSHA512KDF") == 0) {
+ kdf_algo = BCRYPT_SHA512_ALGORITHM;
+ } else {
+ //unreachable
+ return NULL;
+ }
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+
+ BCRYPT_ALG_HANDLE kaHandle = NULL;
+
+ jint pub_flag = get_keyflag(env, pubkey);
+ if (pub_flag == KEYFLAG_OTHER) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native public key.");
+ return NULL;
+ }
+ jbyteArray meta = get_meta(env, pubkey);
+
+ if (NT_FAILURE(status = init_use_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, pub_flag, meta, params))) {
+ return NULL;
+ }
+
+ BCRYPT_KEY_HANDLE pkey = NULL;
+ BCRYPT_KEY_HANDLE skey = NULL;
+
+ jmethodID get_data_priv = (*env)->GetMethodID(env, pubkey_class, "getData", "()[B");
+ jbyteArray pubkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, pubkey, get_data_priv);
+
+ jint pub_length = (*env)->GetArrayLength(env, pubkey_barray);
+ jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey_barray, NULL);
+ if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair(pub)\n", status);
+ BCryptCloseAlgorithmProvider(kaHandle, 0);
+ (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT);
+
+ jint priv_flag = get_keyflag(env, privkey);
+ if (priv_flag == KEYFLAG_OTHER) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native private key.");
+ return NULL;
+ }
+
+ jmethodID get_data_pub = (*env)->GetMethodID(env, privkey_class, "getData", "()[B");
+ jbyteArray privkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, privkey, get_data_pub);
+
+ jint priv_length = (*env)->GetArrayLength(env, privkey_barray);
+ jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey_barray, NULL);
+ if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair(priv)\n", status);
+ BCryptCloseAlgorithmProvider(kaHandle, 0);
+ BCryptDestroyKey(pkey);
+ (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT);
+
+ BCRYPT_SECRET_HANDLE ka = NULL;
+
+ if (NT_FAILURE(status = BCryptSecretAgreement(skey, pkey, &ka, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSecretAgreement\n", status);
+ BCryptCloseAlgorithmProvider(kaHandle, 0);
+ BCryptDestroyKey(pkey);
+ BCryptDestroyKey(skey);
+ return NULL;
+ }
+
+ BCryptBufferDesc paramList = { 0 };
+ BCryptBuffer kdfParams[1] = { 0 };
+ kdfParams[0].BufferType = KDF_HASH_ALGORITHM;
+ kdfParams[0].cbBuffer = (DWORD)((wcslen(kdf_algo) + 1) * sizeof(WCHAR));
+ kdfParams[0].pvBuffer = (PVOID)kdf_algo;
+ paramList.cBuffers = 1;
+ paramList.pBuffers = kdfParams;
+ paramList.ulVersion = BCRYPTBUFFER_VERSION;
+
+ //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(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, &paramList, NULL, 0, &bufSize, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptDeriveKey(length only)\n", status);
+ return NULL;
+ }
+
+ PBYTE derived = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, &paramList, derived, bufSize, &bufSize, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptDeriveKey(whole)\n", status);
+ return NULL;
+ }
+
+ jbyteArray result = (*env)->NewByteArray(env, bufSize);
+ jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL);
+ memcpy(result_data, derived, bufSize);
+ (*env)->ReleaseByteArrayElements(env, result, result_data, 0);
+
+ free(derived);
+ BCryptDestroyKey(pkey);
+ BCryptDestroyKey(skey);
+ BCryptDestroySecret(ka);
+ BCryptCloseAlgorithmProvider(kaHandle, 0);
+ return result;
+}
+
+static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) {
+ jclass mscng_sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Mscng");
+ jfieldID type_id = (*env)->GetFieldID(env, mscng_sig_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring)(*env)->GetObjectField(env, self, type_id);
+ const char* type_data = (*env)->GetStringUTFChars(env, type, NULL);
+ LPCWSTR hash_algo;
+ if (strcmp(type_data, "SHA1withECDSA") == 0) {
+ hash_algo = BCRYPT_SHA1_ALGORITHM;
+ } else if (strcmp(type_data, "SHA256withECDSA") == 0) {
+ hash_algo = BCRYPT_SHA256_ALGORITHM;
+ } else if (strcmp(type_data, "SHA384withECDSA") == 0) {
+ hash_algo = BCRYPT_SHA384_ALGORITHM;
+ } else if (strcmp(type_data, "SHA512withECDSA") == 0) {
+ hash_algo = BCRYPT_SHA512_ALGORITHM;
+ } else {
+ //unreachable
+ return NULL;
+ }
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+ return hash_algo;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jobject privkey, jobject params) {
+ NTSTATUS status;
+ LPCWSTR hash_algo = get_sighash_algo(env, self);
+
+ BCRYPT_ALG_HANDLE sigHandle = NULL;
+
+ jint keyflag = get_keyflag(env, privkey);
+ if (keyflag == KEYFLAG_OTHER) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native private key.");
+ return NULL;
+ }
+ jbyteArray meta = get_meta(env, privkey);
+
+ if (NT_FAILURE(status = init_use_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, keyflag, meta, params))) {
+ return NULL;
+ }
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&sigHandle, BCRYPT_ECDSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ return NULL;
+ }
+
+ BCRYPT_ALG_HANDLE hashHandle = NULL;
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ return NULL;
+ }
+
+ DWORD dummy = 0;
+ DWORD hash_len = 0;
+ if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGetProperty(hash len)\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ return NULL;
+ }
+
+ PBYTE hash = calloc(hash_len, 1);
+
+ jint data_len = (*env)->GetArrayLength(env, data);
+ jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL);
+ if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptHash\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+
+ BCRYPT_KEY_HANDLE skey = NULL;
+
+ jmethodID get_data = (*env)->GetMethodID(env, privkey_class, "getData", "()[B");
+ jbyteArray privkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, privkey, get_data);
+
+
+ jint priv_length = (*env)->GetArrayLength(env, privkey_barray);
+ jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey_barray, NULL);
+ if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT);
+
+ DWORD sig_len = 0;
+ if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSignHash(len only)\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ return NULL;
+ }
+
+ jbyteArray sig = (*env)->NewByteArray(env, sig_len);
+ jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL);
+ if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSignHash(do)\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0);
+
+ free(hash);
+
+ BCryptDestroyKey(skey);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+
+ return sig;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jobject pubkey, jobject params) {
+ NTSTATUS status;
+ LPCWSTR hash_algo = get_sighash_algo(env, self);
+
+ BCRYPT_ALG_HANDLE sigHandle = NULL;
+
+ jint keyflag = get_keyflag(env, pubkey);
+ if (keyflag == KEYFLAG_OTHER) { // TODO: This is not necessary
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native public key.");
+ return JNI_FALSE;
+ }
+ jbyteArray meta = get_meta(env, pubkey);
+
+ if (NT_FAILURE(status = init_use_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, keyflag, meta, params))) {
+ return JNI_FALSE;
+ }
+
+ BCRYPT_ALG_HANDLE hashHandle = NULL;
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ return JNI_FALSE;
+ }
+
+ DWORD dummy = 0;
+ DWORD hash_len = 0;
+ if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGetProperty(hash len)\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ return JNI_FALSE;
+ }
+
+ PBYTE hash = calloc(hash_len, 1);
+
+ jint data_len = (*env)->GetArrayLength(env, data);
+ jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL);
+ if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptHash\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+ return JNI_FALSE;
+ }
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+
+ BCRYPT_KEY_HANDLE pkey = NULL;
+
+ jmethodID get_data = (*env)->GetMethodID(env, pubkey_class, "getData", "()[B");
+ jbyteArray pubkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, pubkey, get_data);
+
+
+ jint pub_length = (*env)->GetArrayLength(env, pubkey_barray);
+ jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey_barray, NULL);
+ if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT);
+ return JNI_FALSE;
+ }
+ (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT);
+
+ jint sig_len = (*env)->GetArrayLength(env, sig);
+ jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL);
+ NTSTATUS result = BCryptVerifySignature(pkey, NULL, hash, hash_len, sig_data, sig_len, 0);
+ (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT);
+
+ free(hash);
+
+ BCryptDestroyKey(pkey);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+
+ if (result == STATUS_SUCCESS) {
+ return JNI_TRUE;
+ } else if (result == STATUS_INVALID_SIGNATURE) {
+ return JNI_FALSE;
+ } else {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptVerifySignature\n", status);
+ return JNI_FALSE;
+ }
+} \ 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..dcdaa1b 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -1,344 +1,857 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class cz_crcs_ectester_standalone_libs_TomcryptLib */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_TomcryptLib
-#define _Included_cz_crcs_ectester_standalone_libs_TomcryptLib
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
- * Method: createProvider
- * Signature: ()Ljava/security/Provider;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_createProvider
- (JNIEnv *, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
- * Method: getCurves
- * Signature: ()Ljava/util/Set;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves
- (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392LL
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE 2147483639L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS 0L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES 1L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES 2L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840LL
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739LL
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
- * Method: setup
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024TomCrypt_setup
- (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
- * Method: keysizeSupported
- * Signature: (I)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
- * Method: paramsSupported
- * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_paramsSupported
- (JNIEnv *, jobject, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
- * Method: generate
- * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__ILjava_security_SecureRandom_2
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
- * Method: generate
- * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_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_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
- * Method: generateSecret
- * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
- */
-JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
- * Method: sign
- * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
- */
-JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
- * Method: verify
- * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_BotanLib */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_BotanLib
-#define _Included_cz_crcs_ectester_standalone_libs_BotanLib
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * 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 *, jobject);
-
-/*
- * 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 *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 1421746759512286392LL
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE 2147483639L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS 0L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES 1L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES 2L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 4112578634029874840LL
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -4298000515446427739LL
-/*
- * 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 *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * 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 *, jobject, jint);
-
-/*
- * 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 *, jobject, jobject);
-
-/*
- * 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 *, jobject, jint, jobject);
-
-/*
- * 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 *, jobject, jobject, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * 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 *, jobject, jbyteArray, jbyteArray, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * 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 *, jobject, jbyteArray, jbyteArray, jobject);
-
-/*
- * 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 *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class cz_crcs_ectester_standalone_libs_TomcryptLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_TomcryptLib
+#define _Included_cz_crcs_ectester_standalone_libs_TomcryptLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739i64
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024TomCrypt_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_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_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_BotanLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_BotanLib
+#define _Included_cz_crcs_ectester_standalone_libs_BotanLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * 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 *, jobject);
+
+/*
+ * 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 *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 1421746759512286392i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -4298000515446427739i64
+/*
+ * 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 *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * 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 *, jobject, jint);
+
+/*
+ * 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 *, jobject, jobject);
+
+/*
+ * 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 *, jobject, jint, jobject);
+
+/*
+ * 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 *, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * 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 *, jobject, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * 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 *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * 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 *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#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 1421746759512286392i64
+#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 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -4298000515446427739i64
+/*
+ * 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
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * 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 *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * 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 *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#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 1421746759512286392i64
+#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 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -4298000515446427739i64
+/*
+ * 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
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Openssl_generateSecret
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_MscngLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_MscngLib
+#define _Included_cz_crcs_ectester_standalone_libs_MscngLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MscngLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MscngLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 1421746759512286392i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -4298000515446427739i64
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_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_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng
+ * Method: generateSecret
+ * Signature: (Ljava/security/interfaces/ECPublicKey;Ljava/security/interfaces/ECPrivateKey;Ljava/security/spec/AlgorithmParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret
+ (JNIEnv *, jobject, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng
+ * Method: sign
+ * Signature: ([BLjava/security/interfaces/ECPrivateKey;Ljava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign
+ (JNIEnv *, jobject, jbyteArray, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng
+ * Method: verify
+ * Signature: ([B[BLjava/security/interfaces/ECPublicKey;Ljava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject, jobject);
+
+#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..259630c
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
@@ -0,0 +1,567 @@
+#include "native.h"
+#include <string.h>
+#include <stdio.h>
+
+#include <openssl/conf.h>
+#include <openssl/opensslv.h>
+#include <openssl/objects.h>
+#include <openssl/obj_mac.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+
+#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, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V");
+
+ jstring name = (*env)->NewStringUTF(env, OPENSSL_VERSION_TEXT);
+ long ver_hi = (OPENSSL_VERSION_NUMBER & 0xff000000L) >> 28;
+ long ver_mid = (OPENSSL_VERSION_NUMBER & 0xff0000L) >> 20;
+ long ver_low = (OPENSSL_VERSION_NUMBER & 0xff00L) >> 12;
+ double version = (double)ver_hi + ((double)ver_mid/10) + ((double)ver_low/100);
+
+ 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();
+
+ INIT_PROVIDER(env, provider_class);
+
+ ADD_KPG(env, self, "EC", "Openssl");
+ ADD_KA(env, self, "ECDH", "OpensslECDH");
+ ADD_SIG(env, self, "NONEwithECDSA", "OpensslECDSAwithNONE");
+
+ 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, "<init>", "()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, "<init>", "(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, 0);
+ jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, 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);
+ if (!result) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_new_curve_GFp.");
+ BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn);
+ return NULL;
+ }
+
+ g_point = EC_POINT_new(result);
+ if(!EC_POINT_set_affine_coordinates_GFp(result, g_point, gx_bn, gy_bn, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_POINT_set_affine_coordinates_GFp.");
+ BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result);
+ return 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);
+ if (!result) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_new_curve_GF2m.");
+ BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn);
+ return NULL;
+ }
+
+ g_point = EC_POINT_new(result);
+ if(!EC_POINT_set_affine_coordinates_GF2m(result, g_point, gx_bn, gy_bn, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_POINT_set_affine_coordinates_GF2m.");
+ BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result);
+ return 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);
+
+ if (!EC_GROUP_set_generator(result, g_point, n_bn, h_bn)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_set_generator.");
+ BN_free(n_bn); BN_free(h_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result);
+ return NULL;
+ }
+
+ EC_POINT_free(g_point);
+ 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();
+ if (!EC_GROUP_get_curve_GFp(curve, p, a, b, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_curve_GFp.");
+ BN_free(p); BN_free(a); BN_free(b);
+ return NULL;
+ }
+
+ jobject p_int = bignum_to_biginteger(env, p);
+
+ jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "<init>", "(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();
+ if (!EC_POINT_get_affine_coordinates_GFp(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_POINT_get_affine_coordinates_GFp.");
+ BN_free(a); BN_free(b); BN_free(gx); BN_free(gy);
+ return NULL;
+ }
+
+ } else if (field_type == NID_X9_62_characteristic_two_field) {
+ a = BN_new();
+ b = BN_new();
+ if (!EC_GROUP_get_curve_GF2m(curve, NULL, a, b, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_curve_GF2m.");
+ BN_free(a); BN_free(b);
+ return 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);
+ if (!EC_GROUP_get_trinomial_basis(curve, &ks_data[0])) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_trinomial_basis.");
+ BN_free(a); BN_free(b);
+ (*env)->ReleaseIntArrayElements(env, ks, ks_data, JNI_ABORT);
+ return NULL;
+ }
+ } else if (basis_type == NID_X9_62_ppBasis) {
+ ks = (*env)->NewIntArray(env, 3);
+ ks_data = (*env)->GetIntArrayElements(env, ks, NULL);
+ if (!EC_GROUP_get_pentanomial_basis(curve, &ks_data[0], &ks_data[1], &ks_data[2])) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_pentanomial_basis.");
+ BN_free(a); BN_free(b);
+ (*env)->ReleaseIntArrayElements(env, ks, ks_data, JNI_ABORT);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+ (*env)->ReleaseIntArrayElements(env, ks, ks_data, 0);
+
+ jint m = EC_GROUP_get_degree(curve);
+
+ jmethodID f2m_field_init = (*env)->GetMethodID(env, f2m_field_class, "<init>", "(I[I)V");
+ field = (*env)->NewObject(env, f2m_field_class, f2m_field_init, m, ks);
+
+ gx = BN_new();
+ gy = BN_new();
+ if (!EC_POINT_get_affine_coordinates_GF2m(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_POINT_get_affine_coordinates_GF2m.");
+ BN_free(a); BN_free(b); BN_free(gx); BN_free(gy);
+ return 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, "<init>", "(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);
+ 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, "<init>", "(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, "<init>", "(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);
+ if (!EC_KEY_generate_key(key)) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error generating key, EC_KEY_generate_key.");
+ EC_KEY_free(key);
+ return NULL;
+ }
+
+ 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, 0);
+
+ unsigned long key_len = 2*key_bytes + 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, 0);
+
+ 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, "<init>", "([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, "<init>", "([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, "<init>", "(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;
+ }
+}
+
+EC_KEY *barray_to_pubkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray pub) {
+ EC_KEY *result = EC_KEY_new();
+ EC_KEY_set_group(result, curve);
+ jsize pub_len = (*env)->GetArrayLength(env, pub);
+ jbyte *pub_data = (*env)->GetByteArrayElements(env, pub, NULL);
+ EC_POINT *pub_point = EC_POINT_new(curve);
+ EC_POINT_oct2point(curve, pub_point, pub_data, pub_len, NULL);
+ (*env)->ReleaseByteArrayElements(env, pub, pub_data, JNI_ABORT);
+ EC_KEY_set_public_key(result, pub_point);
+ EC_POINT_free(pub_point);
+ return result;
+}
+
+EC_KEY *barray_to_privkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray priv) {
+ EC_KEY *result = EC_KEY_new();
+ EC_KEY_set_group(result, curve);
+ jsize priv_len = (*env)->GetArrayLength(env, priv);
+ jbyte *priv_data = (*env)->GetByteArrayElements(env, priv, NULL);
+ BIGNUM *s = BN_bin2bn(priv_data, priv_len, NULL);
+ (*env)->ReleaseByteArrayElements(env, priv, priv_data, JNI_ABORT);
+ EC_KEY_set_private_key(result, s);
+ BN_free(s);
+ return result;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Openssl_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) {
+ EC_GROUP *curve = create_curve(env, params);
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found.");
+ return NULL;
+ }
+
+ EC_KEY *pub = barray_to_pubkey(env, curve, pubkey);
+ EC_KEY *priv = barray_to_privkey(env, curve, privkey);
+
+ int field_size = EC_GROUP_get_degree(curve);
+ size_t secret_len = (field_size + 7)/8;
+
+ //TODO: Do more KeyAgreements here, but will have to do the hash-fun manually,
+ // probably using the ECDH_KDF_X9_62 by wrapping it and dynamically choosing the EVP_MD. from the type string.
+ jbyteArray result = (*env)->NewByteArray(env, secret_len);
+ jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL);
+ if (ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL) <= 0) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key.");
+ EC_KEY_free(pub); EC_KEY_free(priv); EC_GROUP_free(curve);
+ (*env)->ReleaseByteArrayElements(env, result, result_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, result, result_data, 0);
+
+ EC_KEY_free(pub);
+ EC_KEY_free(priv);
+ EC_GROUP_free(curve);
+ return result;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) {
+ EC_GROUP *curve = create_curve(env, params);
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found.");
+ return NULL;
+ }
+
+ EC_KEY *priv = barray_to_privkey(env, curve, privkey);
+
+ jsize data_size = (*env)->GetArrayLength(env, data);
+ jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+ // TODO: Do more Signatures here, maybe use the EVP interface to get to the hashes easier and not hash manually?
+ ECDSA_SIG *signature = ECDSA_do_sign(data_data, data_size, priv);
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ if (!signature) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error signing, ECDSA_do_sign.");
+ EC_KEY_free(priv); EC_GROUP_free(curve);
+ return NULL;
+ }
+
+ jsize sig_len = i2d_ECDSA_SIG(signature, NULL);
+ jbyteArray result = (*env)->NewByteArray(env, sig_len);
+ jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL);
+ jbyte *result_data_ptr = result_data;
+ i2d_ECDSA_SIG(signature, (unsigned char **)&result_data_ptr);
+ (*env)->ReleaseByteArrayElements(env, result, result_data, 0);
+
+ ECDSA_SIG_free(signature);
+ EC_KEY_free(priv);
+ EC_GROUP_free(curve);
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_verify(JNIEnv *env, jobject self, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params) {
+ EC_GROUP *curve = create_curve(env, params);
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found.");
+ return JNI_FALSE;
+ }
+
+ EC_KEY *pub = barray_to_pubkey(env, curve, pubkey);
+
+ jsize sig_len = (*env)->GetArrayLength(env, signature);
+ jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL);
+ jbyte *sig_data_ptr = sig_data;
+ ECDSA_SIG *sig_obj = d2i_ECDSA_SIG(NULL, (const unsigned char **)&sig_data_ptr, sig_len);
+ (*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
+
+ jsize data_size = (*env)->GetArrayLength(env, data);
+ jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+ int result = ECDSA_do_verify(data_data, data_size, sig_obj, pub);
+ if (result < 0) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error verifying, ECDSA_do_verify.");
+ EC_KEY_free(pub); EC_GROUP_free(curve); ECDSA_SIG_free(sig_obj);
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ return JNI_FALSE;
+ }
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+
+ ECDSA_SIG_free(sig_obj);
+ EC_KEY_free(pub);
+ EC_GROUP_free(curve);
+ return (result == 1) ? JNI_TRUE : JNI_FALSE;
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
index 29ee707..d609a48 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;
@@ -229,6 +230,17 @@ static ltc_ecc_set_type* create_curve(JNIEnv *env, jobject params) {
return curve;
}
+static void free_curve(ltc_ecc_set_type *curve) {
+ if (curve) {
+ free((void*)curve->prime);
+ free((void*)curve->B);
+ free((void*)curve->order);
+ free((void*)curve->Gx);
+ free((void*)curve->Gy);
+ free(curve);
+ }
+}
+
static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
ecc_key key;
int err;
@@ -240,7 +252,7 @@ static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
jbyteArray pub_bytes = (*env)->NewByteArray(env, key_len);
jbyte *key_pub = (*env)->GetByteArrayElements(env, pub_bytes, NULL);
ecc_ansi_x963_export(&key, key_pub, &key_len);
- (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, JNI_COMMIT);
+ (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, 0);
jobject ec_param_spec = create_ec_param_spec(env, curve);
@@ -251,7 +263,7 @@ static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
jbyteArray priv_bytes = (*env)->NewByteArray(env, curve->size);
jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
ltc_mp.unsigned_write(key.k, key_priv);
- (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, JNI_COMMIT);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
@@ -286,7 +298,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai
if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
ltc_ecc_set_type *curve = create_curve(env, params);
jobject result = generate_from_curve(env, curve);
- free(curve);
+ free_curve(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;");
@@ -356,13 +368,13 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
ecc_key pub;
if (!pubkey_from_bytes(env, pubkey, curve, &pub)) {
- free(curve);
+ free_curve(curve);
return NULL;
}
ecc_key priv;
if (!privkey_from_bytes(env, privkey, curve, &priv)) {
- free(curve);
+ free_curve(curve);
return NULL;
}
@@ -371,17 +383,17 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
int err;
if ((err = ecc_shared_secret(&priv, &pub, result, &output_len)) != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
- free(curve);
+ free_curve(curve);
return NULL;
}
jbyteArray output = (*env)->NewByteArray(env, curve->size);
jbyte *output_data = (*env)->GetByteArrayElements(env, output, NULL);
memcpy(output_data, result, curve->size);
- (*env)->ReleaseByteArrayElements(env, output, output_data, JNI_COMMIT);
+ (*env)->ReleaseByteArrayElements(env, output, output_data, 0);
ltc_cleanup_multi(&pub.pubkey.x, &pub.pubkey.y, &pub.pubkey.z, &priv.k, NULL);
- free(curve);
+ free_curve(curve);
return output;
}
@@ -390,7 +402,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
ecc_key priv;
if (!privkey_from_bytes(env, privkey, curve, &priv)) {
- free(curve);
+ free_curve(curve);
return NULL;
}
@@ -402,7 +414,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
int err;
if ((err = ecc_sign_hash(data_data, data_size, result, &output_len, &ltc_prng, find_prng("yarrow"), &priv)) != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
- free(curve);
+ free_curve(curve);
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
return NULL;
}
@@ -412,9 +424,9 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jbyteArray output = (*env)->NewByteArray(env, output_len);
jbyte *output_data = (*env)->GetByteArrayElements(env, output, NULL);
memcpy(output_data, result, output_len);
- (*env)->ReleaseByteArrayElements(env, output, output_data, JNI_COMMIT);
+ (*env)->ReleaseByteArrayElements(env, output, output_data, 0);
- free(curve);
+ free_curve(curve);
return output;
}
@@ -423,7 +435,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
ecc_key pub;
if (!pubkey_from_bytes(env, pubkey, curve, &pub)) {
- free(curve);
+ free_curve(curve);
return JNI_FALSE;
}
@@ -437,7 +449,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
int result;
if ((err = ecc_verify_hash(sig_data, sig_size, data_data, data_size, &result, &pub)) != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
- free(curve);
+ free_curve(curve);
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
return JNI_FALSE;
@@ -445,6 +457,6 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
- free(curve);
+ free_curve(curve);
return result;
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/output/TextTestWriter.java b/src/cz/crcs/ectester/standalone/output/TextTestWriter.java
index 972af18..bf9ec7d 100644
--- a/src/cz/crcs/ectester/standalone/output/TextTestWriter.java
+++ b/src/cz/crcs/ectester/standalone/output/TextTestWriter.java
@@ -1,8 +1,12 @@
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;
+import cz.crcs.ectester.standalone.ECTesterStandalone;
+import cz.crcs.ectester.standalone.test.base.StandaloneTestable;
+import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
import java.io.PrintStream;
@@ -14,15 +18,38 @@ public class TextTestWriter extends BaseTextTestWriter {
super(output);
}
+ private String causeString(Object cause) {
+ if (cause == null) {
+ return "";
+ } else if (cause instanceof Exception) {
+ Exception ex = ((Exception) cause);
+ return " -> " + ex.getClass().getCanonicalName() + " : " + ex.getMessage();
+ } else {
+ return cause.toString();
+ }
+ }
+
@Override
protected String testableString(Testable t) {
- //TODO
+ if (t instanceof StandaloneTestable) {
+ StandaloneTestable<?> testable = (StandaloneTestable) t;
+ String stage = testable.getStage().name();
+ String exception = causeString(testable.getException());
+ String errorCause = causeString(testable.errorCause());
+ return stage + exception + errorCause;
+ }
return "";
}
@Override
protected String deviceString(TestSuite suite) {
- //TODO
+ if (suite instanceof StandaloneTestSuite) {
+ StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite;
+ StringBuilder sb = new StringBuilder();
+ sb.append("═══ ").append(Colors.underline("ECTester version:")).append(" ").append(ECTesterStandalone.VERSION).append(System.lineSeparator());
+ sb.append("═══ ").append(Colors.underline("Library:")).append(" ").append(standaloneSuite.getLibrary().name()).append(System.lineSeparator());
+ return sb.toString();
+ }
return "";
}
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/output/XMLTestWriter.java b/src/cz/crcs/ectester/standalone/output/XMLTestWriter.java
index d2b16d8..812634f 100644
--- a/src/cz/crcs/ectester/standalone/output/XMLTestWriter.java
+++ b/src/cz/crcs/ectester/standalone/output/XMLTestWriter.java
@@ -4,9 +4,12 @@ import cz.crcs.ectester.common.output.BaseXMLTestWriter;
import cz.crcs.ectester.common.test.TestSuite;
import cz.crcs.ectester.common.test.Testable;
import cz.crcs.ectester.common.util.ByteUtil;
-import cz.crcs.ectester.standalone.test.KeyAgreementTestable;
-import cz.crcs.ectester.standalone.test.KeyGeneratorTestable;
-import cz.crcs.ectester.standalone.test.SignatureTestable;
+import cz.crcs.ectester.standalone.ECTesterStandalone;
+import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable;
+import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable;
+import cz.crcs.ectester.standalone.test.base.SignatureTestable;
+import cz.crcs.ectester.standalone.test.base.StandaloneTestable;
+import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
import org.w3c.dom.Element;
import javax.xml.parsers.ParserConfigurationException;
@@ -95,25 +98,59 @@ public class XMLTestWriter extends BaseXMLTestWriter {
return sigElem;
}
+ private Element stageElement(StandaloneTestable<?> t) {
+ Element result = doc.createElement("stage");
+ result.setTextContent(t.getStage().name());
+ return result;
+ }
+
+ private String causeObject(Object cause) {
+ if (cause == null) {
+ return "";
+ } else if (cause instanceof Exception) {
+ Exception ex = ((Exception) cause);
+ return ex.getClass().getCanonicalName() + " : " + ex.getMessage();
+ } else {
+ return cause.toString();
+ }
+ }
+
@Override
protected Element testableElement(Testable t) {
Element result = doc.createElement("test");
- if (t instanceof KeyGeneratorTestable) {
- result.setAttribute("type", "key-pair-generator");
- result.appendChild(kgtElement((KeyGeneratorTestable) t));
- } else if (t instanceof KeyAgreementTestable) {
- result.setAttribute("type", "key-agreement");
- result.appendChild(kaElement((KeyAgreementTestable) t));
- } else if (t instanceof SignatureTestable) {
- result.setAttribute("type", "signature");
- result.appendChild(sigElement((SignatureTestable) t));
+ if (t instanceof StandaloneTestable) {
+ StandaloneTestable<?> testable = (StandaloneTestable) t;
+ if (t instanceof KeyGeneratorTestable) {
+ result.setAttribute("type", "key-pair-generator");
+ result.appendChild(kgtElement((KeyGeneratorTestable) t));
+ } else if (t instanceof KeyAgreementTestable) {
+ result.setAttribute("type", "key-agreement");
+ result.appendChild(kaElement((KeyAgreementTestable) t));
+ } else if (t instanceof SignatureTestable) {
+ result.setAttribute("type", "signature");
+ result.appendChild(sigElement((SignatureTestable) t));
+ }
+ result.appendChild(stageElement(testable));
+ Element exception = doc.createElement("exception");
+ exception.setTextContent(causeObject(testable.getException()) + causeObject(testable.errorCause()));
+ result.appendChild(exception);
}
return result;
}
@Override
protected Element deviceElement(TestSuite suite) {
- //TODO
+ if (suite instanceof StandaloneTestSuite) {
+ StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite;
+ Element result = doc.createElement("device");
+ result.setAttribute("type", "library");
+ result.setAttribute("ectester", ECTesterStandalone.VERSION);
+
+ Element name = doc.createElement("name");
+ name.setTextContent(standaloneSuite.getLibrary().name());
+ result.appendChild(name);
+ return result;
+ }
return null;
}
}
diff --git a/src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java b/src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
index dfc6813..433624a 100644
--- a/src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
+++ b/src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
@@ -4,15 +4,19 @@ import cz.crcs.ectester.common.output.BaseYAMLTestWriter;
import cz.crcs.ectester.common.test.TestSuite;
import cz.crcs.ectester.common.test.Testable;
import cz.crcs.ectester.common.util.ByteUtil;
-import cz.crcs.ectester.standalone.test.KeyAgreementTestable;
-import cz.crcs.ectester.standalone.test.KeyGeneratorTestable;
-import cz.crcs.ectester.standalone.test.SignatureTestable;
+import cz.crcs.ectester.standalone.ECTesterStandalone;
+import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable;
+import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable;
+import cz.crcs.ectester.standalone.test.base.SignatureTestable;
+import cz.crcs.ectester.standalone.test.base.StandaloneTestable;
+import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
import java.io.PrintStream;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
/**
@@ -24,7 +28,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> keyObject(Key key) {
- Map<String, Object> kObject = new HashMap<>();
+ Map<String, Object> kObject = new LinkedHashMap<>();
if (key == null) {
return kObject;
}
@@ -35,7 +39,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> kaObject(KeyAgreementTestable kat) {
- Map<String, Object> katObject = new HashMap<>();
+ Map<String, Object> katObject = new LinkedHashMap<>();
katObject.put("algo", kat.getKa().getAlgorithm());
katObject.put("secret", ByteUtil.bytesToHex(kat.getSecret()));
@@ -48,10 +52,10 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> kgtObject(KeyGeneratorTestable kgt) {
- Map<String, Object> kgtObject = new HashMap<>();
+ Map<String, Object> kgtObject = new LinkedHashMap<>();
kgtObject.put("algo", kgt.getKpg().getAlgorithm());
- Map<String, Object> keypair = new HashMap<>();
+ Map<String, Object> keypair = new LinkedHashMap<>();
if (kgt.getKeyPair() != null) {
PublicKey pkey = kgt.getKeyPair().getPublic();
Map<String, Object> pubObject = keyObject(pkey);
@@ -67,32 +71,55 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> sigObject(SignatureTestable sig) {
- Map<String, Object> sigObject = new HashMap<>();
+ Map<String, Object> sigObject = new LinkedHashMap<>();
sigObject.put("algo", sig.getSig().getAlgorithm());
sigObject.put("verified", sig.getVerified());
sigObject.put("raw", ByteUtil.bytesToHex(sig.getSignature()));
return sigObject;
}
+ private String causeObject(Object cause) {
+ if (cause == null) {
+ return "";
+ } else if (cause instanceof Exception) {
+ Exception ex = ((Exception) cause);
+ return ex.getClass().getCanonicalName() + " : " + ex.getMessage();
+ } else {
+ return cause.toString();
+ }
+ }
+
@Override
protected Map<String, Object> testableObject(Testable t) {
- Map<String, Object> result = new HashMap<>();
- if (t instanceof KeyGeneratorTestable) {
- result.put("type", "key-pair-generator");
- result.put("key-pair-generator", kgtObject((KeyGeneratorTestable) t));
- } else if (t instanceof KeyAgreementTestable) {
- result.put("type", "key-agreement");
- result.put("key-agreement", kaObject((KeyAgreementTestable) t));
- } else if (t instanceof SignatureTestable) {
- result.put("type", "signature");
- result.put("signature", sigObject((SignatureTestable) t));
+ Map<String, Object> result = new LinkedHashMap<>();
+ if (t instanceof StandaloneTestable) {
+ StandaloneTestable<?> testable = (StandaloneTestable) t;
+ if (t instanceof KeyGeneratorTestable) {
+ result.put("type", "key-pair-generator");
+ result.put("key-pair-generator", kgtObject((KeyGeneratorTestable) t));
+ } else if (t instanceof KeyAgreementTestable) {
+ result.put("type", "key-agreement");
+ result.put("key-agreement", kaObject((KeyAgreementTestable) t));
+ } else if (t instanceof SignatureTestable) {
+ result.put("type", "signature");
+ result.put("signature", sigObject((SignatureTestable) t));
+ }
+ result.put("stage", testable.getStage().name());
+ result.put("exception", causeObject(testable.getException()) + causeObject(testable.errorCause()));
}
return result;
}
@Override
protected Map<String, Object> deviceObject(TestSuite suite) {
- //TODO
+ if (suite instanceof StandaloneTestSuite) {
+ StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite;
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("type", "library");
+ result.put("ectester", ECTesterStandalone.VERSION);
+ result.put("name", standaloneSuite.getLibrary().name());
+ return result;
+ }
return null;
}
}
diff --git a/src/cz/crcs/ectester/standalone/test/KeyAgreementTestable.java b/src/cz/crcs/ectester/standalone/test/KeyAgreementTestable.java
deleted file mode 100644
index de9356b..0000000
--- a/src/cz/crcs/ectester/standalone/test/KeyAgreementTestable.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package cz.crcs.ectester.standalone.test;
-
-import cz.crcs.ectester.common.test.BaseTestable;
-import cz.crcs.ectester.common.test.TestException;
-
-import javax.crypto.KeyAgreement;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.ECParameterSpec;
-
-/**
- * @author Jan Jancar johny@neuromancer.sk
- */
-public class KeyAgreementTestable extends BaseTestable {
- private KeyAgreement ka;
- private ECPrivateKey privateKey;
- private ECPublicKey publicKey;
- private KeyGeneratorTestable kgtPrivate;
- private KeyGeneratorTestable kgtPublic;
- private AlgorithmParameterSpec spec;
- private byte[] secret;
-
- public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey) {
- this.ka = ka;
- this.privateKey = privateKey;
- this.publicKey = publicKey;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, ECParameterSpec spec) {
- this(ka, privateKey, publicKey);
- this.spec = spec;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, ECParameterSpec spec) {
- this(ka, privateKey, null, spec);
- this.kgtPublic = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, ECParameterSpec spec) {
- this(ka, null, publicKey, spec);
- this.kgtPrivate = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, ECParameterSpec spec) {
- this(ka, (ECPrivateKey) null, null, spec);
- this.kgtPrivate = privKgt;
- this.kgtPublic = pubKgt;
- }
-
- public KeyAgreement getKa() {
- return ka;
- }
-
- public ECPublicKey getPublicKey() {
- return publicKey;
- }
-
- public ECPrivateKey getPrivateKey() {
- return privateKey;
- }
-
- public byte[] getSecret() {
- if (!hasRun) {
- return null;
- }
- return secret;
- }
-
- @Override
- public void run() throws TestException {
- if (kgtPrivate != null) {
- privateKey = (ECPrivateKey) kgtPrivate.getKeyPair().getPrivate();
- }
-
- if (kgtPublic != null) {
- publicKey = (ECPublicKey) kgtPublic.getKeyPair().getPublic();
- }
-
- try {
- if (spec != null) {
- ka.init(privateKey, spec);
- } else {
- ka.init(privateKey);
- }
- } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
- ok = false;
- error = true;
- hasRun = true;
- return;
- }
-
- try {
- ka.doPhase(publicKey, true);
- } catch (IllegalStateException e) {
- ok = false;
- hasRun = true;
- return;
- } catch (InvalidKeyException e) {
- ok = false;
- error = true;
- hasRun = true;
- return;
- }
-
- try {
- secret = ka.generateSecret();
- } catch (IllegalStateException isex) {
- ok = false;
- hasRun = true;
- return;
- } catch (UnsupportedOperationException uoe) {
- ok = false;
- error = true;
- hasRun = false;
- return;
- }
-
- ok = true;
- hasRun = true;
- }
-}
diff --git a/src/cz/crcs/ectester/standalone/test/SignatureTestable.java b/src/cz/crcs/ectester/standalone/test/SignatureTestable.java
deleted file mode 100644
index e434337..0000000
--- a/src/cz/crcs/ectester/standalone/test/SignatureTestable.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package cz.crcs.ectester.standalone.test;
-
-import cz.crcs.ectester.common.test.BaseTestable;
-import cz.crcs.ectester.common.test.TestException;
-
-import java.security.InvalidKeyException;
-import java.security.SecureRandom;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-
-public class SignatureTestable extends BaseTestable {
- private Signature sig;
- private ECPrivateKey signKey;
- private ECPublicKey verifyKey;
- private KeyGeneratorTestable kgt;
- private byte[] data;
- private byte[] signature;
- private boolean verified;
-
- public SignatureTestable(Signature sig, ECPrivateKey signKey, ECPublicKey verifyKey, byte[] data) {
- this.sig = sig;
- this.signKey = signKey;
- this.verifyKey = verifyKey;
- this.data = data;
- if (data == null) {
- SecureRandom random = new SecureRandom();
- this.data = new byte[32];
- random.nextBytes(this.data);
- }
- }
-
- public SignatureTestable(Signature sig, KeyGeneratorTestable kgt, byte[] data) {
- this(sig, null, null, data);
- this.kgt = kgt;
- }
-
- public Signature getSig() {
- return sig;
- }
-
- public byte[] getData() {
- return data;
- }
-
- public byte[] getSignature() {
- return signature;
- }
-
- public boolean getVerified() {
- return verified;
- }
-
- @Override
- public void run() throws TestException {
- if (kgt != null) {
- signKey = (ECPrivateKey) kgt.getKeyPair().getPrivate();
- verifyKey = (ECPublicKey) kgt.getKeyPair().getPublic();
- }
-
- try {
- sig.initSign(signKey);
- } catch (InvalidKeyException e) {
- throw new TestException(e);
- }
-
- try {
- sig.update(data);
- } catch (SignatureException e) {
- ok = false;
- hasRun = true;
- return;
- }
-
- try {
- signature = sig.sign();
- } catch (SignatureException e) {
- ok = false;
- hasRun = true;
- return;
- }
-
- try {
- sig.initVerify(verifyKey);
- } catch (InvalidKeyException e) {
- throw new TestException(e);
- }
-
- try {
- sig.update(data);
- } catch (SignatureException e) {
- ok = false;
- hasRun = true;
- return;
- }
-
- try {
- verified = sig.verify(signature);
- } catch (SignatureException e) {
- ok = false;
- hasRun = true;
- }
- ok = true;
- hasRun = true;
- }
-}
diff --git a/src/cz/crcs/ectester/standalone/test/KeyAgreementTest.java b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java
index 5f697c4..bfd39fc 100644
--- a/src/cz/crcs/ectester/standalone/test/KeyAgreementTest.java
+++ b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java
@@ -1,9 +1,8 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.base;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.SimpleTest;
import cz.crcs.ectester.common.test.TestCallback;
-import cz.crcs.ectester.common.test.TestException;
import java.util.Arrays;
@@ -32,7 +31,8 @@ public class KeyAgreementTest extends SimpleTest<KeyAgreementTestable> {
return new KeyAgreementTest(ka, new TestCallback<KeyAgreementTestable>() {
@Override
public Result apply(KeyAgreementTestable keyAgreementTestable) {
- return new Result(Result.Value.fromExpected(expected, keyAgreementTestable.ok(), keyAgreementTestable.error()));
+ Result.Value value = Result.Value.fromExpected(expected, keyAgreementTestable.ok(), keyAgreementTestable.error());
+ return new Result(value, value.description());
}
});
}
@@ -43,15 +43,7 @@ public class KeyAgreementTest extends SimpleTest<KeyAgreementTestable> {
@Override
public String getDescription() {
- return "KeyAgreement " + testable.getKa().getAlgorithm();
- }
-
- @Override
- public void run() throws TestException {
- if (hasRun)
- return;
- testable.run();
- result = callback.apply(testable);
- hasRun = true;
+ String keyAlgo = testable.getKeyAlgorithm() == null ? "" : " (" + testable.getKeyAlgorithm() + ")";
+ return "KeyAgreement " + testable.getKa().getAlgorithm() + keyAlgo;
}
}
diff --git a/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
new file mode 100644
index 0000000..1382c28
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
@@ -0,0 +1,170 @@
+package cz.crcs.ectester.standalone.test.base;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECParameterSpec;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestable.KeyAgreementStage> {
+ private KeyAgreement ka;
+ private ECPrivateKey privateKey;
+ private ECPublicKey publicKey;
+ private KeyGeneratorTestable kgtPrivate;
+ private KeyGeneratorTestable kgtPublic;
+ private AlgorithmParameterSpec spec;
+ private String keyAlgo;
+ private byte[] secret;
+ private SecretKey derived;
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey) {
+ this.ka = ka;
+ this.privateKey = privateKey;
+ this.publicKey = publicKey;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, String keyAlgo) {
+ this(ka, privateKey, publicKey);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, ECParameterSpec spec) {
+ this(ka, privateKey, publicKey);
+ this.spec = spec;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, ECParameterSpec spec, String keyAlgo) {
+ this(ka, privateKey, publicKey, spec);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, ECParameterSpec spec) {
+ this(ka, privateKey, null, spec);
+ this.kgtPublic = kgt;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, ECParameterSpec spec, String keyAlgo) {
+ this(ka, kgt, privateKey, spec);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, ECParameterSpec spec) {
+ this(ka, null, publicKey, spec);
+ this.kgtPrivate = kgt;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, ECParameterSpec spec, String keyAlgo) {
+ this(ka, publicKey, kgt, spec);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, ECParameterSpec spec) {
+ this(ka, (ECPrivateKey) null, null, spec);
+ this.kgtPrivate = privKgt;
+ this.kgtPublic = pubKgt;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, ECParameterSpec spec, String keyAlgo) {
+ this(ka, privKgt, pubKgt, spec);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public String getKeyAlgorithm() {
+ return keyAlgo;
+ }
+
+ public KeyAgreement getKa() {
+ return ka;
+ }
+
+ public ECPublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ public ECPrivateKey getPrivateKey() {
+ return privateKey;
+ }
+
+ public byte[] getSecret() {
+ if (!hasRun) {
+ return null;
+ }
+ return secret;
+ }
+
+ public SecretKey getDerivedKey() {
+ if (!hasRun) {
+ return null;
+ }
+ return derived;
+ }
+
+ @Override
+ public void run() {
+ try {
+ stage = KeyAgreementStage.GetPrivate;
+ if (kgtPrivate != null) {
+ privateKey = (ECPrivateKey) kgtPrivate.getKeyPair().getPrivate();
+ }
+
+ stage = KeyAgreementStage.GetPublic;
+ if (kgtPublic != null) {
+ publicKey = (ECPublicKey) kgtPublic.getKeyPair().getPublic();
+ }
+
+ stage = KeyAgreementStage.Init;
+ try {
+ if (spec != null) {
+ ka.init(privateKey, spec);
+ } else {
+ ka.init(privateKey);
+ }
+ } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = KeyAgreementStage.DoPhase;
+ try {
+ ka.doPhase(publicKey, true);
+ } catch (IllegalStateException | InvalidKeyException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = KeyAgreementStage.GenerateSecret;
+ try {
+ if (keyAlgo != null) {
+ derived = ka.generateSecret(keyAlgo);
+ secret = derived.getEncoded();
+ } else {
+ secret = ka.generateSecret();
+ }
+ } catch (IllegalStateException | UnsupportedOperationException e) {
+ failOnException(e);
+ return;
+ }
+
+ ok = true;
+ } catch (Exception ex) {
+ ok = false;
+ error = true;
+ errorCause = ex;
+ }
+ hasRun = true;
+ }
+
+ public enum KeyAgreementStage {
+ GetPrivate,
+ GetPublic,
+ Init,
+ DoPhase,
+ GenerateSecret
+ }
+}
diff --git a/src/cz/crcs/ectester/standalone/test/KeyGeneratorTest.java b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java
index 93273ca..b232456 100644
--- a/src/cz/crcs/ectester/standalone/test/KeyGeneratorTest.java
+++ b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java
@@ -1,9 +1,8 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.base;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.SimpleTest;
import cz.crcs.ectester.common.test.TestCallback;
-import cz.crcs.ectester.common.test.TestException;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -17,7 +16,8 @@ public class KeyGeneratorTest extends SimpleTest<KeyGeneratorTestable> {
return new KeyGeneratorTest(kg, new TestCallback<KeyGeneratorTestable>() {
@Override
public Result apply(KeyGeneratorTestable keyGenerationTestable) {
- return new Result(Result.Value.fromExpected(expected, keyGenerationTestable.ok(), keyGenerationTestable.error()));
+ Result.Value value = Result.Value.fromExpected(expected, keyGenerationTestable.ok(), keyGenerationTestable.error());
+ return new Result(value, value.description());
}
});
}
@@ -30,13 +30,4 @@ public class KeyGeneratorTest extends SimpleTest<KeyGeneratorTestable> {
public String getDescription() {
return "KeyPairGenerator " + testable.getKpg().getAlgorithm();
}
-
- @Override
- public void run() throws TestException {
- if (hasRun)
- return;
- testable.run();
- result = callback.apply(testable);
- hasRun = true;
- }
}
diff --git a/src/cz/crcs/ectester/standalone/test/KeyGeneratorTestable.java b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
index 3fca168..c05d6e3 100644
--- a/src/cz/crcs/ectester/standalone/test/KeyGeneratorTestable.java
+++ b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
@@ -1,14 +1,14 @@
-package cz.crcs.ectester.standalone.test;
-
-import cz.crcs.ectester.common.test.BaseTestable;
-import cz.crcs.ectester.common.test.TestException;
+package cz.crcs.ectester.standalone.test.base;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.spec.ECParameterSpec;
-public class KeyGeneratorTestable extends BaseTestable {
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class KeyGeneratorTestable extends StandaloneTestable<KeyGeneratorTestable.KeyGeneratorStage> {
private KeyPair kp;
private KeyPairGenerator kpg;
private int keysize = 0;
@@ -37,20 +37,34 @@ public class KeyGeneratorTestable extends BaseTestable {
}
@Override
- public void run() throws TestException {
+ public void run() {
try {
- if (spec != null) {
- kpg.initialize(spec);
- } else if (keysize != 0) {
- kpg.initialize(keysize);
+ stage = KeyGeneratorStage.Init;
+ try {
+ if (spec != null) {
+ kpg.initialize(spec);
+ } else if (keysize != 0) {
+ kpg.initialize(keysize);
+ }
+ } catch (InvalidAlgorithmParameterException e) {
+ failOnException(e);
+ return;
}
- } catch (InvalidAlgorithmParameterException e) {
- hasRun = true;
+
+ stage = KeyGeneratorStage.GenKeyPair;
+ kp = kpg.genKeyPair();
+
+ ok = true;
+ } catch (Exception ex) {
ok = false;
- return;
+ error = true;
+ errorCause = ex;
}
- kp = kpg.genKeyPair();
hasRun = true;
- ok = true;
+ }
+
+ public enum KeyGeneratorStage {
+ Init,
+ GenKeyPair
}
}
diff --git a/src/cz/crcs/ectester/standalone/test/SignatureTest.java b/src/cz/crcs/ectester/standalone/test/base/SignatureTest.java
index 9746b91..d8b3e0f 100644
--- a/src/cz/crcs/ectester/standalone/test/SignatureTest.java
+++ b/src/cz/crcs/ectester/standalone/test/base/SignatureTest.java
@@ -1,9 +1,8 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.base;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.SimpleTest;
import cz.crcs.ectester.common.test.TestCallback;
-import cz.crcs.ectester.common.test.TestException;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -17,7 +16,8 @@ public class SignatureTest extends SimpleTest<SignatureTestable> {
return new SignatureTest(kg, new TestCallback<SignatureTestable>() {
@Override
public Result apply(SignatureTestable signatureTestable) {
- return new Result(Result.Value.fromExpected(expected, signatureTestable.ok(), signatureTestable.error()));
+ Result.Value value = Result.Value.fromExpected(expected, signatureTestable.ok(), signatureTestable.error());
+ return new Result(value, value.description());
}
});
}
@@ -30,13 +30,4 @@ public class SignatureTest extends SimpleTest<SignatureTestable> {
public String getDescription() {
return "Signature " + testable.getSig().getAlgorithm();
}
-
- @Override
- public void run() throws TestException {
- if (hasRun)
- return;
- testable.run();
- result = callback.apply(testable);
- hasRun = true;
- }
}
diff --git a/src/cz/crcs/ectester/standalone/test/base/SignatureTestable.java b/src/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
new file mode 100644
index 0000000..b8db7b8
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
@@ -0,0 +1,130 @@
+package cz.crcs.ectester.standalone.test.base;
+
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class SignatureTestable extends StandaloneTestable<SignatureTestable.SignatureStage> {
+ private Signature sig;
+ private ECPrivateKey signKey;
+ private ECPublicKey verifyKey;
+ private KeyGeneratorTestable kgt;
+ private byte[] data;
+ private byte[] signature;
+ private boolean verified;
+
+ public SignatureTestable(Signature sig, ECPrivateKey signKey, ECPublicKey verifyKey, byte[] data) {
+ this.sig = sig;
+ this.signKey = signKey;
+ this.verifyKey = verifyKey;
+ this.data = data;
+ if (data == null) {
+ SecureRandom random = new SecureRandom();
+ this.data = new byte[64];
+ random.nextBytes(this.data);
+ }
+ }
+
+ public SignatureTestable(Signature sig, KeyGeneratorTestable kgt, byte[] data) {
+ this(sig, null, null, data);
+ this.kgt = kgt;
+ }
+
+ public Signature getSig() {
+ return sig;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ public byte[] getSignature() {
+ return signature;
+ }
+
+ public boolean getVerified() {
+ return verified;
+ }
+
+ @Override
+ public void run() {
+ try {
+ stage = SignatureStage.GetKeys;
+ if (kgt != null) {
+ signKey = (ECPrivateKey) kgt.getKeyPair().getPrivate();
+ verifyKey = (ECPublicKey) kgt.getKeyPair().getPublic();
+ }
+
+ stage = SignatureStage.InitSign;
+ try {
+ sig.initSign(signKey);
+ } catch (InvalidKeyException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.UpdateSign;
+ try {
+ sig.update(data);
+ } catch (SignatureException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.Sign;
+ try {
+ signature = sig.sign();
+ } catch (SignatureException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.InitVerify;
+ try {
+ sig.initVerify(verifyKey);
+ } catch (InvalidKeyException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.UpdateVerify;
+ try {
+ sig.update(data);
+ } catch (SignatureException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.Verify;
+ try {
+ verified = sig.verify(signature);
+ } catch (SignatureException e) {
+ failOnException(e);
+ return;
+ }
+
+ ok = verified;
+ } catch (Exception ex) {
+ ok = false;
+ error = true;
+ errorCause = ex;
+ }
+ hasRun = true;
+ }
+
+ public enum SignatureStage {
+ GetKeys,
+ InitSign,
+ UpdateSign,
+ Sign,
+ InitVerify,
+ UpdateVerify,
+ Verify
+ }
+}
diff --git a/src/cz/crcs/ectester/standalone/test/base/StandaloneTestable.java b/src/cz/crcs/ectester/standalone/test/base/StandaloneTestable.java
new file mode 100644
index 0000000..47bffc1
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/test/base/StandaloneTestable.java
@@ -0,0 +1,25 @@
+package cz.crcs.ectester.standalone.test.base;
+
+import cz.crcs.ectester.common.test.BaseTestable;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public abstract class StandaloneTestable<T extends Enum<T>> extends BaseTestable {
+ protected T stage;
+ protected Exception exception;
+
+ public T getStage() {
+ return stage;
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+
+ protected void failOnException(Exception ex) {
+ ok = false;
+ hasRun = true;
+ exception = ex;
+ }
+}
diff --git a/src/cz/crcs/ectester/standalone/test/StandaloneDefaultSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
index 42d2e54..1c14ecc 100644
--- a/src/cz/crcs/ectester/standalone/test/StandaloneDefaultSuite.java
+++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
@@ -1,4 +1,4 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.suites;
import cz.crcs.ectester.common.cli.TreeCommandLine;
import cz.crcs.ectester.common.ec.EC_Curve;
@@ -9,11 +9,13 @@ import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent;
import cz.crcs.ectester.standalone.consts.SignatureIdent;
+import cz.crcs.ectester.standalone.test.base.*;
import javax.crypto.KeyAgreement;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.spec.ECParameterSpec;
+import java.util.Optional;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -21,18 +23,42 @@ import java.security.spec.ECParameterSpec;
public class StandaloneDefaultSuite extends StandaloneTestSuite {
public StandaloneDefaultSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli) {
- super(writer, cfg, cli, "default", "The default test suite run basic support of ECDH and ECDSA.");
+ super(writer, cfg, cli, "default", "The default test suite run basic support of ECDH and ECDSA.", "Supports options:", "\t - gt/kpg-type", "\t - kt/ka-type", "\t - st/sig-type", "\t - key-type");
}
@Override
protected void runTests() throws Exception {
- String kpgAlgo = cli.getOptionValue("test.kpg-type", "EC");
+ String kpgAlgo = cli.getOptionValue("test.kpg-type");
String kaAlgo = cli.getOptionValue("test.ka-type");
String sigAlgo = cli.getOptionValue("test.sig-type");
+ String keyAlgo = cli.getOptionValue("test.key-type", "AES");
+
+
+ KeyPairGeneratorIdent kpgIdent;
+ if (kpgAlgo == null) {
+ // try EC, if not, fail with: need to specify kpg algo.
+ Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream()
+ .filter((ident) -> ident.contains("EC"))
+ .findFirst();
+ if (kpgIdentOpt.isPresent()) {
+ kpgIdent = kpgIdentOpt.get();
+ } else {
+ System.err.println("The default KeyPairGenerator algorithm type of \"EC\" was not found. Need to specify a type.");
+ return;
+ }
+ } else {
+ // try the specified, if not, fail with: wrong kpg algo/not found.
+ Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream()
+ .filter((ident) -> ident.contains(kpgAlgo))
+ .findFirst();
+ if (kpgIdentOpt.isPresent()) {
+ kpgIdent = kpgIdentOpt.get();
+ } else {
+ System.err.println("The KeyPairGenerator algorithm type of \"" + kpgAlgo + "\" was not found.");
+ return;
+ }
+ }
- KeyPairGeneratorIdent kpgIdent = cfg.selected.getKPGs().stream()
- .filter((ident) -> ident.contains(kpgAlgo))
- .findFirst().get();
KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider());
KeyGeneratorTestable kgtOne;
@@ -63,7 +89,13 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) {
if (kaAlgo == null || kaIdent.contains(kaAlgo)) {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- doTest(KeyAgreementTest.expect(new KeyAgreementTestable(ka, kgtOne, kgtOther, spec), Result.ExpectedValue.SUCCESS));
+ KeyAgreementTestable testable;
+ if (kaIdent.requiresKeyAlgo()) {
+ testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec, keyAlgo);
+ } else {
+ testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec);
+ }
+ doTest(KeyAgreementTest.expect(testable, Result.ExpectedValue.SUCCESS));
}
}
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
diff --git a/src/cz/crcs/ectester/standalone/test/StandaloneTestSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
index ad404c8..e4e0013 100644
--- a/src/cz/crcs/ectester/standalone/test/StandaloneTestSuite.java
+++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
@@ -1,12 +1,10 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.suites;
import cz.crcs.ectester.common.cli.TreeCommandLine;
import cz.crcs.ectester.common.output.TestWriter;
import cz.crcs.ectester.common.test.TestSuite;
-import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.ECTesterStandalone;
-
-import java.security.NoSuchAlgorithmException;
+import cz.crcs.ectester.standalone.libs.ProviderECLibrary;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -15,9 +13,13 @@ public abstract class StandaloneTestSuite extends TestSuite {
TreeCommandLine cli;
ECTesterStandalone.Config cfg;
- public StandaloneTestSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli, String name, String description) {
+ public StandaloneTestSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli, String name, String... description) {
super(writer, name, description);
this.cfg = cfg;
this.cli = cli;
}
+
+ public ProviderECLibrary getLibrary() {
+ return cfg.selected;
+ }
}