aboutsummaryrefslogtreecommitdiff
path: root/standalone/src
diff options
context:
space:
mode:
authorJán Jančár2024-08-09 17:24:59 +0200
committerGitHub2024-08-09 17:24:59 +0200
commit65ddb496e2090581e40bce003f6c14490e6cf5fb (patch)
treeee309580ce217c3eea4bc998eb4cd1cef9257bca /standalone/src
parent3cd8dd83f10a8b2f761d77099e9e1b0e1deab183 (diff)
parentc6b752a7a8980372ff6a5f49660f94d9495e5f33 (diff)
downloadECTester-65ddb496e2090581e40bce003f6c14490e6cf5fb.tar.gz
ECTester-65ddb496e2090581e40bce003f6c14490e6cf5fb.tar.zst
ECTester-65ddb496e2090581e40bce003f6c14490e6cf5fb.zip
Diffstat (limited to 'standalone/src')
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java187
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java12
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java3
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java16
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java12
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java4
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java4
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java1
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java184
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java80
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java24
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java4
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java11
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java20
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java12
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java8
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java8
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java28
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java4
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java20
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java2
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java10
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile40
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp47
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c316
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c18
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp27
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c6
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c23
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c46
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h119
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c32
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c53
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h37
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc192
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c29
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h25
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h34
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c187
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h28
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h20
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc123
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c22
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h24
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h32
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c21
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h13
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c16
-rw-r--r--standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java1
-rw-r--r--standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java139
60 files changed, 2151 insertions, 233 deletions
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 4f76639..04537f0 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -31,6 +31,7 @@ import cz.crcs.ectester.common.test.TestException;
import cz.crcs.ectester.common.util.ByteUtil;
import cz.crcs.ectester.common.util.ECUtil;
import cz.crcs.ectester.common.util.FileUtil;
+import cz.crcs.ectester.common.util.Util;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent;
@@ -104,12 +105,52 @@ public class ECTesterStandalone {
if (!System.getProperty("os.name").startsWith("Windows")) {
FileUtil.write(LIB_RESOURCE_DIR + "lib_timing.so", reqs.resolve("lib_timing.so"));
- System.load(reqs.resolve("lib_timing.so").toString());
-
+ FileUtil.write(LIB_RESOURCE_DIR + "lib_preload.so", reqs.resolve("lib_preload.so"));
+ FileUtil.write(LIB_RESOURCE_DIR + "lib_prng.so", reqs.resolve("lib_prng.so"));
FileUtil.write(LIB_RESOURCE_DIR + "lib_csignals.so", reqs.resolve("lib_csignals.so"));
- System.load(reqs.resolve("lib_csignals.so").toString());
FileUtil.write(LIB_RESOURCE_DIR + "lib_cppsignals.so", reqs.resolve("lib_cppsignals.so"));
- System.load(reqs.resolve("lib_cppsignals.so").toString());
+
+ String preloadLibPath = reqs.resolve("lib_preload.so").toAbsolutePath().toString();
+ String preload = System.getenv("LD_PRELOAD");
+ if (preload == null && !cli.hasOption("no-preload")) {
+ ProcessBuilder builder = new ProcessBuilder();
+ Map<String, String> env = builder.environment();
+ env.put("LD_PRELOAD", preloadLibPath);
+
+ ProcessHandle.Info info = ProcessHandle.current().info();
+ List<String> argList = new LinkedList<>();
+ if (info.command().isPresent()) {
+ argList.add(info.command().get());
+ } else {
+ System.err.println("Cannot locate command to spawn preloaded-subprocess.");
+ return;
+ }
+ if (info.arguments().isPresent()) {
+ argList.addAll(List.of(info.arguments().get()));
+ } else {
+ System.err.println("Cannot locate arguments to spawn preloaded-subprocess.");
+ return;
+ }
+ builder.command(argList);
+ builder.inheritIO();
+
+ Process process = builder.start();
+ int result;
+ while (true) {
+ try {
+ result = process.waitFor();
+ break;
+ } catch (InterruptedException ignored) {
+ }
+ }
+ System.exit(result);
+ } else {
+ // Load the utility libs.
+ System.load(reqs.resolve("lib_prng.so").toString());
+ System.load(reqs.resolve("lib_timing.so").toString());
+ System.load(reqs.resolve("lib_csignals.so").toString());
+ System.load(reqs.resolve("lib_cppsignals.so").toString());
+ }
}
List<ProviderECLibrary> libObjects = new LinkedList<>();
@@ -191,7 +232,15 @@ public class ECTesterStandalone {
Option output = Option.builder("o").longOpt("output").desc("Output into file <output_file>. The file can be prefixed by the format (one of text,yml,xml), such as: xml:<output_file>.").hasArgs().argName("output_file").optionalArg(false).numberOfArgs(1).build();
Option outputRaw = Option.builder("o").longOpt("output").desc("Output CSV into file <output_file>.").hasArgs().argName("output_file").optionalArg(false).numberOfArgs(1).build();
Option quiet = Option.builder("q").longOpt("quiet").desc("Do not output to stdout.").build();
- Option timeSource = Option.builder("ts").longOpt("time-source").desc("Use a given native timing source: {rdtsc, monotonic, monotonic-raw, cputime-process, cputime-thread, perfcount}").hasArgs().argName("source").optionalArg(false).numberOfArgs(1).build();
+ Option timeSource = Option.builder("ts").longOpt("time-source").desc("Use a given native timing source: {rdtsc, monotonic, monotonic-raw, cputime-process, cputime-thread}").hasArgs().argName("source").optionalArg(false).numberOfArgs(1).build();
+ Option prngSeed = Option.builder("ps").longOpt("prng-seed").desc("Use a deterministic PRNG with the given [seed] (hexadecimal) in the library.").hasArgs().argName("seed").optionalArg(false).numberOfArgs(1).build();
+ Option file = Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build();
+ Option message = Option.builder("d").longOpt("data").desc("Sign the given [message].").hasArgs().argName("message").optionalArg(false).numberOfArgs(1).build();
+ Option messageSeed = Option.builder("ds").longOpt("data-seed").desc("Use a deterministic PRNG with the given [seed] (hexadecimal) to generate the messages.").hasArgs().argName("seed").optionalArg(false).numberOfArgs(1).build();
+ OptionGroup ecdsaMessage = new OptionGroup();
+ ecdsaMessage.addOption(file);
+ ecdsaMessage.addOption(message);
+ ecdsaMessage.addOption(messageSeed);
Options testOpts = new Options();
testOpts.addOption(bits);
@@ -199,6 +248,7 @@ public class ECTesterStandalone {
testOpts.addOption(curveName);
testOpts.addOption(output);
testOpts.addOption(quiet);
+ testOpts.addOption(prngSeed);
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());
@@ -215,6 +265,7 @@ public class ECTesterStandalone {
ecdhOpts.addOption(curveName);
ecdhOpts.addOption(outputRaw);
ecdhOpts.addOption(timeSource);
+ ecdhOpts.addOption(prngSeed);
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());
@@ -231,12 +282,13 @@ public class ECTesterStandalone {
ecdsaOpts.addOption(curveName);
ecdsaOpts.addOption(outputRaw);
ecdsaOpts.addOption(timeSource);
+ ecdsaOpts.addOption(prngSeed);
ecdsaOpts.addOptionGroup(privateKey);
ecdsaOpts.addOptionGroup(publicKey);
ecdsaOpts.addOption(Option.builder().longOpt("fixed").desc("Perform all ECDSA with fixed keypair.").build());
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());
+ ecdsaOpts.addOptionGroup(ecdsaMessage);
ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts, "Perform EC based Signature.");
actions.put("ecdsa", ecdsa);
@@ -246,6 +298,7 @@ public class ECTesterStandalone {
generateOpts.addOption(curveName);
generateOpts.addOption(outputRaw);
generateOpts.addOption(timeSource);
+ generateOpts.addOption(prngSeed);
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, "Generate EC keypairs.");
@@ -283,6 +336,7 @@ public class ECTesterStandalone {
opts.addOption(Option.builder("V").longOpt("version").desc("Print version info.").build());
opts.addOption(Option.builder("h").longOpt("help").desc("Print help(about <command>).").hasArg().argName("command").optionalArg(true).build());
opts.addOption(Option.builder("C").longOpt("color").desc("Print stuff with color, requires ANSI terminal.").build());
+ opts.addOption(Option.builder().longOpt("no-preload").desc("Do not use LD_PRELOAD.").build());
return optParser.parse(opts, args);
}
@@ -307,6 +361,7 @@ public class ECTesterStandalone {
System.out.println(Colors.bold("\t\t- Fullname: ") + lib.getProvider().getName());
System.out.println(Colors.bold("\t\t- Version: ") + lib.getProvider().getVersionStr());
System.out.println(Colors.bold("\t\t- Supports native timing: ") + lib.getNativeTimingSupport().toString());
+ System.out.println(Colors.bold("\t\t- Supports deterministic PRNG: ") + lib.supportsDeterministicPRNG());
Set<KeyPairGeneratorIdent> kpgs = lib.getKPGs();
if (!kpgs.isEmpty()) {
System.out.println(Colors.bold("\t\t- KeyPairGenerators: ") + kpgs.stream().map(KeyPairGeneratorIdent::getName).sorted().collect(Collectors.joining(", ")));
@@ -409,12 +464,25 @@ public class ECTesterStandalone {
throw new NoSuchAlgorithmException(algo);
}
+ SecureRandom random;
+ if (cli.hasOption("ecdh.prng-seed")) {
+ String seedString = cli.getOptionValue("ecdh.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ random = Util.getRandom(seed);
+ if (!lib.setupDeterministicPRNG(seed)) {
+ System.err.println("Couldn't set PRNG seed.");
+ return;
+ }
+ } else {
+ random = new SecureRandom();
+ }
+
KeyAgreement ka = kaIdent.getInstance(lib.getProvider());
KeyPairGenerator kpg = kpIdent.getInstance(lib.getProvider());
AlgorithmParameterSpec spec = null;
if (cli.hasOption("ecdh.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("ecdh.bits"));
- kpg.initialize(bits);
+ kpg.initialize(bits, random);
} else if (cli.hasOption("ecdh.named-curve")) {
String curveName = cli.getOptionValue("ecdh.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -423,11 +491,15 @@ public class ECTesterStandalone {
return;
}
spec = curve.toSpec();
- kpg.initialize(spec);
+ kpg.initialize(spec, random);
} else if (cli.hasOption("ecdh.curve-name")) {
String curveName = cli.getOptionValue("ecdh.curve-name");
spec = new ECGenParameterSpec(curveName);
- kpg.initialize(spec);
+ kpg.initialize(spec, random);
+ } else if (cli.hasOption("ecdh.prng-seed") && !(lib instanceof NativeECLibrary)) {
+ // TODO: This only happens if at least one of the (pubkey and privkey) needs to be generated.
+ System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options.");
+ return;
}
if (cli.hasOption("ecdh.time-source")) {
@@ -483,9 +555,9 @@ public class ECTesterStandalone {
long elapsed = -System.nanoTime();
if (spec instanceof ECParameterSpec && lib instanceof NativeECLibrary) {
- ka.init(privkey, spec);
+ ka.init(privkey, spec, random);
} else {
- ka.init(privkey);
+ ka.init(privkey, random);
}
ka.doPhase(pubkey, true);
elapsed += System.nanoTime();
@@ -519,8 +591,24 @@ public class ECTesterStandalone {
*
*/
private void ecdsa() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException, SignatureException {
- byte[] data;
- String dataString;
+ ProviderECLibrary lib = cfg.selected;
+
+ SecureRandom random;
+ if (cli.hasOption("ecdsa.prng-seed")) {
+ String seedString = cli.getOptionValue("ecdsa.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ random = Util.getRandom(seed);
+ if (!lib.setupDeterministicPRNG(seed)) {
+ System.err.println("Couldn't set PRNG seed.");
+ return;
+ }
+ } else {
+ random = new SecureRandom();
+ }
+
+ byte[] data = null;
+ String dataString = null;
+ SecureRandom dataRandom = null;
if (cli.hasOption("ecdsa.file")) {
String fileName = cli.getOptionValue("ecdsa.file");
File in = new File(fileName);
@@ -530,13 +618,17 @@ public class ECTesterStandalone {
}
data = Files.readAllBytes(in.toPath());
dataString = "";
+ } else if (cli.hasOption("ecdsa.data")) {
+ dataString = cli.getOptionValue("ecdsa.data");
+ data = ByteUtil.hexToBytes(dataString);
+ } else if (cli.hasOption("ecdsa.data-seed")) {
+ String seedString = cli.getOptionValue("ecdsa.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ dataRandom = Util.getRandom(seed);
} else {
- Random random = new Random();
- data = new byte[32];
- random.nextBytes(data);
- dataString = ByteUtil.bytesToHex(data, false);
+ dataRandom = new SecureRandom();
}
- ProviderECLibrary lib = cfg.selected;
+
String algo = cli.getOptionValue("ecdsa.type", "ECDSA");
SignatureIdent sigIdent = lib.getSigs().stream()
.filter((ident) -> ident.contains(algo))
@@ -571,7 +663,7 @@ public class ECTesterStandalone {
ECParameterSpec spec = null;
if (cli.hasOption("ecdsa.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("ecdsa.bits"));
- kpg.initialize(bits);
+ kpg.initialize(bits, random);
} else if (cli.hasOption("ecdsa.named-curve")) {
String curveName = cli.getOptionValue("ecdsa.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -580,10 +672,14 @@ public class ECTesterStandalone {
return;
}
spec = curve.toSpec();
- kpg.initialize(spec);
+ kpg.initialize(spec, random);
} else if (cli.hasOption("ecdsa.curve-name")) {
String curveName = cli.getOptionValue("ecdsa.curve-name");
- kpg.initialize(new ECGenParameterSpec(curveName));
+ kpg.initialize(new ECGenParameterSpec(curveName), random);
+ } else if (cli.hasOption("ecdsa.prng-seed") && !(lib instanceof NativeECLibrary)) {
+ // TODO: This only happens if at least one of the (pubkey and privkey) needs to be generated.
+ System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options.");
+ return;
}
if (cli.hasOption("ecdsa.time-source")) {
@@ -636,7 +732,12 @@ public class ECTesterStandalone {
}
}
- sig.initSign(privkey);
+ if (dataRandom != null) {
+ data = dataRandom.generateSeed(16);
+ dataString = ByteUtil.bytesToHex(data, false);
+ }
+
+ sig.initSign(privkey, random);
sig.update(data);
long signTime = -System.nanoTime();
@@ -705,10 +806,24 @@ public class ECTesterStandalone {
if (ident == null) {
throw new NoSuchAlgorithmException(algo);
}
+
+ SecureRandom random;
+ if (cli.hasOption("generate.prng-seed")) {
+ String seedString = cli.getOptionValue("generate.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ random = Util.getRandom(seed);
+ if (!lib.setupDeterministicPRNG(seed)) {
+ System.err.println("Couldn't set PRNG seed.");
+ return;
+ }
+ } else {
+ random = new SecureRandom();
+ }
+
KeyPairGenerator kpg = ident.getInstance(lib.getProvider());
if (cli.hasOption("generate.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("generate.bits"));
- kpg.initialize(bits);
+ kpg.initialize(bits, random);
} else if (cli.hasOption("generate.named-curve")) {
String curveName = cli.getOptionValue("generate.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -716,10 +831,13 @@ public class ECTesterStandalone {
System.err.println("Curve not found: " + curveName);
return;
}
- kpg.initialize(curve.toSpec());
+ kpg.initialize(curve.toSpec(), random);
} else if (cli.hasOption("generate.curve-name")) {
String curveName = cli.getOptionValue("generate.curve-name");
- kpg.initialize(new ECGenParameterSpec(curveName));
+ kpg.initialize(new ECGenParameterSpec(curveName), random);
+ } else if (cli.hasOption("generate.prng-seed") && !(lib instanceof NativeECLibrary)) {
+ System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options.");
+ return;
}
if (cli.hasOption("generate.time-source")) {
@@ -818,6 +936,16 @@ public class ECTesterStandalone {
testTo = -1;
}
+ ProviderECLibrary lib = cfg.selected;
+ if (cli.hasOption("test.prng-seed")) {
+ String seedString = cli.getOptionValue("test.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ if (!lib.setupDeterministicPRNG(seed)) {
+ System.err.println("Couldn't set PRNG seed.");
+ return;
+ }
+ }
+
switch (testSuite) {
case "test-vectors":
suite = new StandaloneTestVectorSuite(writer, cfg, cli);
@@ -997,6 +1125,15 @@ public class ECTesterStandalone {
}
}
+ if (cli.isNext("generate") || cli.isNext("ecdh") || cli.isNext("ecdsa") || cli.isNext("test")) {
+ if (cli.hasOption(next + ".prng-seed")) {
+ if (!selected.supportsDeterministicPRNG()) {
+ System.err.printf("Deterministic PRNG is not supported by library %s.%n", selected.name());
+ return false;
+ }
+ }
+ }
+
return true;
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java
index af4d969..06e6b4a 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java
@@ -16,4 +16,10 @@ public class BoringsslLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ // This is provided by the native preload that hooks all randomness sources.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java
index e8f6e13..c072e84 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java
@@ -17,4 +17,10 @@ public class BotanLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java
index e8a4d30..0a7ea8c 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java
@@ -25,4 +25,16 @@ public class BouncyCastleLib extends ProviderECLibrary {
}
return result;
}
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ return true;
+ }
+
+ @Override
+ public boolean setupDeterministicPRNG(byte[] seed) {
+ // This is done by passing the SecureRandom into the individual KeyPairGenerator, KeyAgreement and Signature
+ // instances. Thus, this does nothing.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java
index 66aa9ea..25f2de4 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java
@@ -17,4 +17,10 @@ public class CryptoppLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java
index 83d78ef..d1452a9 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java
@@ -17,4 +17,10 @@ public class GcryptLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ // This is provided by the native preload that hooks all randomness sources.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java
index 115fe00..fa51585 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java
@@ -17,4 +17,10 @@ public class IppcpLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java
index 2dba049..e53399c 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java
@@ -16,4 +16,10 @@ public class LibresslLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ // This is provided by the native preload that hooks all randomness sources.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
index e44598c..efc8cad 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
@@ -17,4 +17,10 @@ public class MbedTLSLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
index c11dbdb..fb4e430 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
@@ -86,5 +86,8 @@ public abstract class NativeECLibrary extends ProviderECLibrary {
@Override
public native long getLastNativeTiming();
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
+
abstract Provider createProvider();
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java
index d4df414..aa90c38 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java
@@ -49,4 +49,10 @@ public class NettleLib extends NativeECLibrary {
}
throw new InvalidAlgorithmParameterException("Unknown curve.");
}
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java
index 61f00a4..69c84bc 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java
@@ -16,4 +16,10 @@ public class OpensslLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
index d9d6749..a9178f6 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
@@ -69,21 +69,29 @@ public abstract class ProviderECLibrary implements ECLibrary {
}
public boolean setNativeTimingType(String type) {
- return false;
+ return false;
}
public long getNativeTimingResolution() {
return 0;
}
- public String getNativeTimingUnit() {
- return null;
- }
+ public String getNativeTimingUnit() {
+ return null;
+ }
public long getLastNativeTiming() {
return 0;
}
+ public boolean supportsDeterministicPRNG() {
+ return false;
+ }
+
+ public boolean setupDeterministicPRNG(byte[] seed) {
+ return false;
+ }
+
@Override
public Set<KeyAgreementIdent> getKAs() {
return getIdents("KeyAgreement", KeyAgreementIdent::get);
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java
index 7209dc3..c38300d 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java
@@ -25,4 +25,16 @@ public class SunECLib extends ProviderECLibrary {
}
return result;
}
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ return true;
+ }
+
+ @Override
+ public boolean setupDeterministicPRNG(byte[] seed) {
+ // This is done by passing the SecureRandom into the individual KeyPairGenerator, KeyAgreement and Signature
+ // instances. Thus, this does nothing.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java
index 8c000a2..e499451 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java
@@ -17,4 +17,10 @@ public class TomcryptLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java b/standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java
index 13a9e72..c3ddea5 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java
@@ -4,6 +4,7 @@ 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.common.util.ByteUtil;
import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.test.base.StandaloneTestable;
import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
@@ -47,7 +48,8 @@ public class TextTestWriter extends BaseTextTestWriter {
if (suite instanceof StandaloneTestSuite) {
StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite;
String sb = "═══ " + Colors.underline("ECTester version:") + " " + ECTesterStandalone.VERSION + System.lineSeparator() +
- "═══ " + Colors.underline("Library:") + " " + standaloneSuite.getLibrary().fullName() + System.lineSeparator();
+ "═══ " + Colors.underline("Library:") + " " + standaloneSuite.getLibrary().fullName() + System.lineSeparator() +
+ "═══ " + Colors.underline("Seed:") + " " + ByteUtil.bytesToHex(standaloneSuite.getSeed()) + System.lineSeparator();
return sb;
}
return "";
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java b/standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java
index 2341fc7..06e7399 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java
@@ -149,6 +149,10 @@ public class XMLTestWriter extends BaseXMLTestWriter {
Element name = doc.createElement("name");
name.setTextContent(standaloneSuite.getLibrary().fullName());
result.appendChild(name);
+
+ Element seed = doc.createElement("seed");
+ seed.setTextContent(ByteUtil.bytesToHex(standaloneSuite.getSeed()));
+ result.appendChild(seed);
return result;
}
return null;
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java b/standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
index 66c5e38..d22c441 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
@@ -117,6 +117,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
result.put("type", "library");
result.put("ectester", ECTesterStandalone.VERSION);
result.put("name", standaloneSuite.getLibrary().fullName());
+ result.put("seed", ByteUtil.bytesToHex(standaloneSuite.getSeed()));
return result;
}
return null;
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
index 579904c..6566a9c 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
@@ -5,6 +5,7 @@ import javax.crypto.SecretKey;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
@@ -17,94 +18,24 @@ public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestabl
private KeyAgreement ka;
private ECPrivateKey privateKey;
private ECPublicKey publicKey;
- private KeyGeneratorTestable kgtPrivate;
- private KeyGeneratorTestable kgtPublic;
- private AlgorithmParameterSpec spec;
- private String keyAlgo;
+ private final KeyGeneratorTestable kgtPrivate;
+ private final KeyGeneratorTestable kgtPublic;
+ private final AlgorithmParameterSpec spec;
+ private final String keyAlgo;
+ private final SecureRandom random;
+
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, null, (ECPublicKey) 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 KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey) {
- this(ka, privateKey, null, (ECParameterSpec) null);
- this.kgtPublic = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, String keyAlgo) {
- this(ka, kgt, privateKey, (ECParameterSpec) null);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt) {
- this(ka, null, publicKey, (ECParameterSpec) null);
- this.kgtPrivate = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, String keyAlgo) {
- this(ka, publicKey, kgt, (ECParameterSpec) null);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt) {
- this(ka, null, (ECPublicKey) null, (ECParameterSpec) null);
- this.kgtPrivate = privKgt;
- this.kgtPublic = pubKgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, String keyAlgo) {
- this(ka, privKgt, pubKgt, (ECParameterSpec) null);
- this.keyAlgo = keyAlgo;
+ KeyAgreementTestable(Builder builder) {
+ this.ka = builder.ka;
+ this.privateKey = builder.privateKey;
+ this.publicKey = builder.publicKey;
+ this.kgtPrivate = builder.kgtPrivate;
+ this.kgtPublic = builder.kgtPublic;
+ this.spec = builder.spec;
+ this.keyAlgo = builder.keyAlgo;
+ this.random = builder.random;
}
public String getKeyAlgorithm() {
@@ -153,9 +84,17 @@ public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestabl
stage = KeyAgreementStage.Init;
try {
if (spec != null) {
- ka.init(privateKey, spec);
+ if (random != null) {
+ ka.init(privateKey, spec, random);
+ } else {
+ ka.init(privateKey, spec);
+ }
} else {
- ka.init(privateKey);
+ if (random != null) {
+ ka.init(privateKey, random);
+ } else {
+ ka.init(privateKey);
+ }
}
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
failOnException(e);
@@ -197,7 +136,12 @@ public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestabl
super.reset();
try {
ka = KeyAgreement.getInstance(ka.getAlgorithm(), ka.getProvider());
- } catch (NoSuchAlgorithmException e) { }
+ } catch (NoSuchAlgorithmException e) {
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
}
public enum KeyAgreementStage {
@@ -207,4 +151,68 @@ public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestabl
DoPhase,
GenerateSecret
}
+
+ public static class Builder {
+ private KeyAgreement ka;
+ private ECPrivateKey privateKey;
+ private ECPublicKey publicKey;
+ private KeyGeneratorTestable kgtPrivate;
+ private KeyGeneratorTestable kgtPublic;
+ private AlgorithmParameterSpec spec;
+ private String keyAlgo;
+ private SecureRandom random;
+
+ public Builder ka(KeyAgreement ka) {
+ this.ka = ka;
+ return this;
+ }
+
+ public Builder privateKey(ECPrivateKey privateKey) {
+ this.privateKey = privateKey;
+ return this;
+ }
+
+ public Builder publicKey(ECPublicKey publicKey) {
+ this.publicKey = publicKey;
+ return this;
+ }
+
+ public Builder privateKgt(KeyGeneratorTestable privateKgt) {
+ this.kgtPrivate = privateKgt;
+ return this;
+ }
+
+ public Builder publicKgt(KeyGeneratorTestable publicKgt) {
+ this.kgtPublic = publicKgt;
+ return this;
+ }
+
+ public Builder spec(AlgorithmParameterSpec spec) {
+ this.spec = spec;
+ return this;
+ }
+
+ public Builder keyAlgo(String keyAlgo) {
+ this.keyAlgo = keyAlgo;
+ return this;
+ }
+
+ public Builder random(SecureRandom random) {
+ this.random = random;
+ return this;
+ }
+
+ public KeyAgreementTestable build() {
+ if (ka == null) {
+ throw new NullPointerException("ka needs to be non-null.");
+ }
+ if ((privateKey == null) == (kgtPrivate == null)) {
+ throw new IllegalStateException("One of (but not both) privateKey or privateKgt needs to be non-null.");
+ }
+ if ((publicKey == null) == (kgtPublic == null)) {
+ throw new IllegalStateException("One of (but not both) publicKey or publicKgt needs to be non-null.");
+ }
+ return new KeyAgreementTestable(this);
+ }
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
index bc44eb8..f9c84e1 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
@@ -3,6 +3,7 @@ package cz.crcs.ectester.standalone.test.base;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
+import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
@@ -15,24 +16,17 @@ public class KeyGeneratorTestable extends StandaloneTestable<KeyGeneratorTestabl
private final KeyPairGenerator kpg;
private int keysize = 0;
private AlgorithmParameterSpec spec = null;
+ private SecureRandom random;
public KeyGeneratorTestable(KeyPairGenerator kpg) {
this.kpg = kpg;
}
- public KeyGeneratorTestable(KeyPairGenerator kpg, int keysize) {
- this.kpg = kpg;
- this.keysize = keysize;
- }
-
- public KeyGeneratorTestable(KeyPairGenerator kpg, ECParameterSpec spec) {
- this.kpg = kpg;
- this.spec = spec;
- }
-
- public KeyGeneratorTestable(KeyPairGenerator kpg, ECGenParameterSpec spec) {
- this.kpg = kpg;
- this.spec = spec;
+ KeyGeneratorTestable(Builder builder) {
+ this.kpg = builder.kpg;
+ this.keysize = builder.keysize;
+ this.spec = builder.spec;
+ this.random = builder.random;
}
public int getKeysize() {
@@ -57,9 +51,17 @@ public class KeyGeneratorTestable extends StandaloneTestable<KeyGeneratorTestabl
stage = KeyGeneratorStage.Init;
try {
if (spec != null) {
- kpg.initialize(spec);
+ if (random != null) {
+ kpg.initialize(spec, random);
+ } else {
+ kpg.initialize(spec);
+ }
} else if (keysize != 0) {
- kpg.initialize(keysize);
+ if (random != null) {
+ kpg.initialize(keysize, random);
+ } else {
+ kpg.initialize(keysize);
+ }
}
} catch (InvalidAlgorithmParameterException e) {
failOnException(e);
@@ -78,8 +80,56 @@ public class KeyGeneratorTestable extends StandaloneTestable<KeyGeneratorTestabl
hasRun = true;
}
+ public static Builder builder() {
+ return new Builder();
+ }
+
public enum KeyGeneratorStage {
Init,
GenKeyPair
}
+
+ public static class Builder {
+ private KeyPairGenerator kpg;
+ private int keysize = 0;
+ private AlgorithmParameterSpec spec = null;
+ private SecureRandom random;
+
+ public Builder() {}
+
+ public Builder keyPairGenerator(KeyPairGenerator kpg) {
+ this.kpg = kpg;
+ return this;
+ }
+
+ public Builder keysize(int keysize) {
+ this.keysize = keysize;
+ return this;
+ }
+
+ public Builder spec(ECGenParameterSpec spec) {
+ this.spec = spec;
+ return this;
+ }
+
+ public Builder spec(ECParameterSpec spec) {
+ this.spec = spec;
+ return this;
+ }
+
+ public Builder random(SecureRandom random) {
+ this.random = random;
+ return this;
+ }
+
+ public KeyGeneratorTestable build() {
+ if (kpg == null) {
+ throw new NullPointerException("kpg mus be non-null.");
+ }
+ if (spec != null && keysize != 0) {
+ throw new IllegalStateException("Only one of spec and keysize can be set.");
+ }
+ return new KeyGeneratorTestable(this);
+ }
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
index 76074e4..5839497 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
@@ -15,32 +15,32 @@ public class SignatureTestable extends StandaloneTestable<SignatureTestable.Sign
private ECPrivateKey signKey;
private ECPublicKey verifyKey;
private KeyGeneratorTestable kgt;
+ private SecureRandom random;
private byte[] data;
private byte[] signature;
private boolean verified;
- public SignatureTestable(Signature sig, ECPrivateKey signKey, ECPublicKey verifyKey, byte[] data) {
+ public SignatureTestable(Signature sig, ECPrivateKey signKey, ECPublicKey verifyKey, byte[] data, SecureRandom random) {
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);
- }
+ this.random = random;
}
- public SignatureTestable(Signature sig, ECPublicKey verifyKey, byte[] data, byte[] signature) {
+ public SignatureTestable(Signature sig, ECPublicKey verifyKey, byte[] data, byte[] signature, SecureRandom random) {
this.sig = sig;
this.verifyKey = verifyKey;
this.data = data;
this.signature = signature;
+ this.random = random;
}
- public SignatureTestable(Signature sig, KeyGeneratorTestable kgt, byte[] data) {
- this(sig, (ECPrivateKey) null, null, data);
+ public SignatureTestable(Signature sig, KeyGeneratorTestable kgt, byte[] data, SecureRandom random) {
+ this.sig = sig;
this.kgt = kgt;
+ this.data = data;
+ this.random = random;
}
public Signature getSig() {
@@ -71,7 +71,11 @@ public class SignatureTestable extends StandaloneTestable<SignatureTestable.Sign
if(signKey != null) {
stage = SignatureStage.InitSign;
try {
- sig.initSign(signKey);
+ if (random != null) {
+ sig.initSign(signKey, random);
+ } else {
+ sig.initSign(signKey);
+ }
} catch (InvalidKeyException e) {
failOnException(e);
return;
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java
index 003d510..5079770 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java
@@ -56,7 +56,7 @@ public class StandaloneCofactorSuite extends StandaloneTestSuite {
KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider());
ECParameterSpec spec = curve.toSpec();
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
@@ -67,7 +67,7 @@ public class StandaloneCofactorSuite extends StandaloneTestSuite {
for (EC_Key.Public pub : keys) {
ECPublicKey ecpub = ECUtil.toPublicKey(pub);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpub, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(kgt).random(getRandom()).build();
Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE);
specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " cofactor key test.", keyAgreement));
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java
index 38d76bc..d838d20 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java
@@ -64,7 +64,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
ECParameterSpec spec = curve.toSpec();
//Generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//Perform KeyAgreement tests
@@ -75,7 +75,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
for (EC_Key.Public pub : curveKeys.getValue()) {
ECPublicKey ecpub = ECUtil.toPublicKey(pub);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpub, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(kgt).random(getRandom()).build();
Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE);
specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", with generated private key, " + pub.getDesc(), keyAgreement));
}
@@ -133,7 +133,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
}
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, curve.toSpec());
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(curve.toSpec()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//perform KeyAgreement tests
@@ -141,7 +141,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) {
if (kaAlgo == null || kaIdent.containsAny(kaTypes)) {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKgt(kgt).privateKgt(kgt).random(getRandom()).build();
kaTests.add(KeyAgreementTest.expectError(testable, dhValue));
}
}
@@ -154,7 +154,8 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
if (sigAlgo == null || sigIdent.containsAny(sigTypes)) {
Signature sig = sigIdent.getInstance(cfg.selected.getProvider());
- SignatureTestable testable = new SignatureTestable(sig, kgt, null);
+ byte[] data = sigIdent.toString().getBytes();
+ SignatureTestable testable = new SignatureTestable(sig, kgt, data, getRandom());
sigTests.add(SignatureTest.expectError(testable, dhValue));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
index ef9d434..a9b82d5 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
@@ -4,6 +4,7 @@ import cz.crcs.ectester.common.cli.TreeCommandLine;
import cz.crcs.ectester.common.ec.EC_Curve;
import cz.crcs.ectester.common.output.TestWriter;
import cz.crcs.ectester.common.test.Result;
+import cz.crcs.ectester.common.util.ECUtil;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
@@ -44,8 +45,8 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
ECParameterSpec spec = null;
if (cli.hasOption("test.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("test.bits"));
- kgtOne = new KeyGeneratorTestable(kpg, bits);
- kgtOther = new KeyGeneratorTestable(kpg, bits);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).keysize(bits).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).keysize(bits).build();
} else if (cli.hasOption("test.named-curve")) {
String curveName = cli.getOptionValue("test.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -54,11 +55,11 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
return;
}
spec = curve.toSpec();
- kgtOne = new KeyGeneratorTestable(kpg, spec);
- kgtOther = new KeyGeneratorTestable(kpg, spec);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(spec).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(spec).build();
} else {
- kgtOne = new KeyGeneratorTestable(kpg);
- kgtOther = new KeyGeneratorTestable(kpg);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build();
}
doTest(KeyGeneratorTest.expect(kgtOne, Result.ExpectedValue.SUCCESS));
@@ -69,9 +70,9 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
KeyAgreementTestable testable;
if (kaIdent.requiresKeyAlgo()) {
- testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec, keyAlgo);
+ testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).keyAlgo(keyAlgo).build();
} else {
- testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec);
+ testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).build();
}
doTest(KeyAgreementTest.expect(testable, Result.ExpectedValue.SUCCESS));
}
@@ -79,7 +80,8 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
if (sigAlgo == null || sigIdent.contains(sigAlgo)) {
Signature sig = sigIdent.getInstance(cfg.selected.getProvider());
- doTest(SignatureTest.expect(new SignatureTestable(sig, kgtOne, null), Result.ExpectedValue.SUCCESS));
+ byte[] data = sigIdent.toString().getBytes();
+ doTest(SignatureTest.expect(new SignatureTestable(sig, kgtOne, data, getRandom()), Result.ExpectedValue.SUCCESS));
}
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java
index d441235..12a9f16 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java
@@ -92,7 +92,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
ECPublicKey ecpub = ECUtil.toPublicKey(EC_Store.getInstance().getObject(EC_Key.Public.class, pubkeyId));
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(ecpriv).publicKey(ecpub).random(getRandom()).build();
Test ecdh = KeyAgreementTest.match(testable, value.getData(0));
Test one = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test " + id + ".", ecdh);
curveTests.add(one);
@@ -107,7 +107,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
ECPrivateKey ecpriv = ECUtil.toPrivateKey(EC_Store.getInstance().getObject(EC_Key.Private.class, openssl_bug.getOtherKey()));
ECPublicKey ecpub = ECUtil.toPublicKey(EC_Store.getInstance().getObject(EC_Key.Public.class, openssl_bug.getOneKey()));
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(ecpriv).publicKey(ecpub).random(getRandom()).build();
Test ecdh = KeyAgreementTest.function(testable, new TestCallback<KeyAgreementTestable>() {
@Override
public Result apply(KeyAgreementTestable testable) {
@@ -129,12 +129,12 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
e.getKey().endsWith("r1") && e.getValue().getField() == javacard.security.KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList());
curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor128p2"));
curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor160p4"));
- Random rand = new Random();
+ Random rand = getRandom();
for (EC_Curve curve : curves) {
ECParameterSpec spec = curve.toSpec();
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//perform ECDH tests
@@ -213,7 +213,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
Arrays.sort(zeros);
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//perform ECDH tests
@@ -247,7 +247,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
private Test ecdhTest(KeyGeneratorTestable kgt, BigInteger SParam, ECParameterSpec spec, String desc, Result.ExpectedValue expect) throws NoSuchAlgorithmException {
ECPrivateKey priv = new RawECPrivateKey(SParam, spec);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, priv);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(priv).publicKgt(kgt).random(getRandom()).build();
return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, KeyAgreementTest.expectError(testable, expect));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java
index 21431ae..da5d19a 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java
@@ -57,9 +57,9 @@ public abstract class StandaloneForeignSuite extends StandaloneTestSuite {
ECParameterSpec spec = curve.toSpec();
ECGenParameterSpec namedSpec = new ECGenParameterSpec(curve.getId());
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
- KeyGeneratorTestable kgtOnNamedCurve = new KeyGeneratorTestable(kpg, namedSpec);
- KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits());
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(spec).build();
+ KeyGeneratorTestable kgtOnNamedCurve = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(namedSpec).build();
+ KeyGeneratorTestable kgtOnDefaultCurve = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).keysize(curve.getBits()).build();
// This is some nasty hacking...
KeyGeneratorTestable theKgt = new KeyGeneratorTestable(kpg) {
@@ -156,7 +156,7 @@ public abstract class StandaloneForeignSuite extends StandaloneTestSuite {
for (EC_Key.Public pub : keys) {
ECPublicKey ecpub = ECUtil.toPublicKey(pub);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpub, theKgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(theKgt).random(getRandom()).build();
Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE);
specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " invalid key test.", keyAgreement));
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java
index 657c2ff..87ad0b3 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java
@@ -7,6 +7,7 @@ import cz.crcs.ectester.common.test.CompoundTest;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.Test;
import cz.crcs.ectester.common.util.ByteUtil;
+import cz.crcs.ectester.common.util.ECUtil;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
@@ -80,7 +81,7 @@ public class StandaloneMiscSuite extends StandaloneTestSuite {
private void testCurve(EC_Curve curve, String catName, KeyPairGenerator kpg, Result.ExpectedValue expected) throws NoSuchAlgorithmException {
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, curve.toSpec());
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(curve.toSpec()).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//perform KeyAgreement tests
@@ -88,7 +89,7 @@ public class StandaloneMiscSuite extends StandaloneTestSuite {
for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) {
if (kaAlgo == null || kaIdent.containsAny(kaTypes)) {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKgt(kgt).privateKgt(kgt).random(getRandom()).build();
kaTests.add(KeyAgreementTest.expectError(testable, expected));
}
}
@@ -101,7 +102,8 @@ public class StandaloneMiscSuite extends StandaloneTestSuite {
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
if (sigAlgo == null || sigIdent.containsAny(sigTypes)) {
Signature sig = sigIdent.getInstance(cfg.selected.getProvider());
- SignatureTestable testable = new SignatureTestable(sig, kgt, hashCurve(curve));
+ byte[] data = sigIdent.toString().getBytes();
+ SignatureTestable testable = new SignatureTestable(sig, kgt, data, getRandom());
sigTests.add(SignatureTest.expectError(testable, expected));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java
index 30a0c0f..46e4141 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java
@@ -38,9 +38,9 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
@Override
protected void runTests() throws Exception {
- String kpgAlgo = cli.getOptionValue("test.kpg-type");
- String kaAlgo = cli.getOptionValue("test.ka-type");
- String sigAlgo = cli.getOptionValue("test.sig-type");
+ String kpgAlgo = cli.getOptionValue("test.kpg-type", "EC");
+ String kaAlgo = cli.getOptionValue("test.ka-type", "ECDH");
+ String sigAlgo = cli.getOptionValue("test.sig-type", "ECDSA");
String keyAlgo = cli.getOptionValue("test.key-type", "AES");
List<String> kpgTypes = kpgAlgo != null ? Arrays.asList(kpgAlgo.split(",")) : new ArrayList<>();
@@ -67,8 +67,8 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider());
if (cli.hasOption("test.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("test.bits"));
- kgtOne = new KeyGeneratorTestable(kpg, bits);
- kgtOther = new KeyGeneratorTestable(kpg, bits);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(bits).random(getRandom()).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(bits).random(getRandom()).build();
} else if (cli.hasOption("test.named-curve")) {
String curveName = cli.getOptionValue("test.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -77,11 +77,11 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
return;
}
spec = curve.toSpec();
- kgtOne = new KeyGeneratorTestable(kpg, spec);
- kgtOther = new KeyGeneratorTestable(kpg, spec);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
} else {
- kgtOne = new KeyGeneratorTestable(kpg);
- kgtOther = new KeyGeneratorTestable(kpg);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build();
}
kpgTests.add(PerformanceTest.repeat(kgtOne, cfg.selected, kpgIdent.getName(), count));
kpgTests.add(PerformanceTest.repeat(kgtOther, cfg.selected, kpgIdent.getName(), count));
@@ -94,9 +94,9 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
KeyAgreementTestable testable;
if (kaIdent.requiresKeyAlgo()) {
- testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec, keyAlgo);
+ testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).keyAlgo(keyAlgo).build();
} else {
- testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec);
+ testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).build();
}
kaTests.add(PerformanceTest.repeat(testable, cfg.selected, kaIdent.getName(), count));
}
@@ -111,10 +111,12 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
if (sigAlgo == null || sigIdent.containsAny(sigTypes)) {
Signature sig = sigIdent.getInstance(cfg.selected.getProvider());
- sigTests.add(PerformanceTest.repeat(new SignatureTestable(sig, kgtOne, null), cfg.selected, sigIdent.getName(), count));
+ byte[] data = sigIdent.toString().getBytes();
+ sigTests.add(PerformanceTest.repeat(new SignatureTestable(sig, kgtOne, data, getRandom()), cfg.selected, sigIdent.getName(), count));
+ // TODO: The following will always fail as a runTest is not done at this point.
if (kgtOne.getKeyPair() != null) {
ECPrivateKey signKey = (ECPrivateKey) kgtOne.getKeyPair().getPrivate();
- sigTestsNoVerification.add(PerformanceTest.repeat(new SignatureTestable(sig, signKey, null, null), cfg.selected, sigIdent.getName(), count));
+ sigTestsNoVerification.add(PerformanceTest.repeat(new SignatureTestable(sig, signKey, null, data, getRandom()), cfg.selected, sigIdent.getName(), count));
}
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java
index 43feb23..740dca7 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java
@@ -61,11 +61,11 @@ public class StandaloneSignatureSuite extends StandaloneTestSuite {
byte[] data = sig.getSigData();
if (data == null) {
- data = defaultData;
+ data = sigIdent.toString().getBytes();
}
Signature signature = sigIdent.getInstance(cfg.selected.getProvider());
- SignatureTestable testable = new SignatureTestable(signature, ecpub, data, sig.getData(0));
+ SignatureTestable testable = new SignatureTestable(signature, ecpub, data, sig.getData(0), getRandom());
doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "ECDSA test of " + sig.getId() + ".", SignatureTest.expectError(testable, expected)));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
index ac164e1..bfea628 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
@@ -3,6 +3,8 @@ 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.common.util.ByteUtil;
+import cz.crcs.ectester.common.util.Util;
import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.consts.Ident;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
@@ -10,6 +12,7 @@ import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent;
import cz.crcs.ectester.standalone.consts.SignatureIdent;
import cz.crcs.ectester.standalone.libs.ProviderECLibrary;
+import java.security.SecureRandom;
import java.util.Optional;
import java.util.Set;
@@ -19,17 +22,34 @@ import java.util.Set;
public abstract class StandaloneTestSuite extends TestSuite {
TreeCommandLine cli;
ECTesterStandalone.Config cfg;
+ SecureRandom random;
+ byte[] seed;
public StandaloneTestSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli, String name, String... description) {
super(writer, name, description);
this.cfg = cfg;
this.cli = cli;
+ if (cli != null && cli.hasOption("test.prng-seed")) {
+ String seedString = cli.getOptionValue("test.prng-seed");
+ this.seed = ByteUtil.hexToBytes(seedString, true);
+ } else {
+ seed = new SecureRandom().generateSeed(16);
+ }
+ this.random = Util.getRandom(seed);
}
public ProviderECLibrary getLibrary() {
return cfg.selected;
}
+ public byte[] getSeed() {
+ return seed;
+ }
+
+ SecureRandom getRandom() {
+ return this.random;
+ }
+
private <T extends Ident> T getIdent(Set<T> options, String choice, String identName, String defaultChoice) {
T ident;
if (choice == null) {
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java
index 111d354..1766953 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java
@@ -56,7 +56,7 @@ public class StandaloneTestVectorSuite extends StandaloneTestSuite {
KeyAgreementIdent kaIdent = KeyAgreementIdent.get("ECDH");
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, privkey, pubkey);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(privkey).publicKey(pubkey).random(getRandom()).build();
doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test vector " + result.getId(), KeyAgreementTest.match(testable, result.getData(0))));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java
index 4634ab0..1a18188 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java
@@ -73,11 +73,11 @@ public class StandaloneWrongSuite extends StandaloneTestSuite {
String type = curve.getField() == javacard.security.KeyPair.ALG_EC_FP ? "FP" : "F2M";
//try generating a keypair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).random(getRandom()).build();
Test ecdh = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE);
doTest(CompoundTest.function(CompoundTest.EXPECT_ALL_SUCCESS, CompoundTest.RUN_ALL_IF_FIRST, "Wrong curve test of " + curve.getBits()
+ "b " + type + ". " + curve.getDesc(), generate, ecdh));
@@ -96,7 +96,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite {
Map<String, EC_Curve> curveMap = EC_Store.getInstance().getObjects(EC_Curve.class, "secg");
List<EC_Curve> curves = curveMap.entrySet().stream().filter((e) -> e.getKey().endsWith("r1") &&
e.getValue().getField() == javacard.security.KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList());
- Random r = new Random();
+ Random r = getRandom();
for (EC_Curve curve : curves) {
short bits = curve.getBits();
final byte[] originalp = curve.getParam(EC_Consts.PARAMETER_FP)[0];
@@ -233,12 +233,12 @@ public class StandaloneWrongSuite extends StandaloneTestSuite {
private Test ecdhTest(ECParameterSpec spec, String desc) throws NoSuchAlgorithmException {
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.FAILURE);
//perform ECDH
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).random(getRandom()).build();
Test ecdh = KeyAgreementTest.expect(testable, Result.ExpectedValue.FAILURE);
return CompoundTest.function(CompoundTest.EXPECT_ALL_SUCCESS, CompoundTest.RUN_ALL_IF_FIRST, desc, generate, ecdh);
}
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile
index 6282574..f947c78 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile
@@ -12,9 +12,9 @@ DEBUG ?= 0
PROJECT_ROOT_PATH ?= ../../../../../../../../../..
ifeq ($(DEBUG), 1)
- CFLAGS+=-g -Wall
+ CFLAGS+=-g -O0 -Wall
LFLAGS+=-g
- CXXFLAGS+=-g -Wall
+ CXXFLAGS+=-g -O0 -Wall
else
CFLAGS+=-O2
LFLAGS+=-O2
@@ -73,6 +73,18 @@ c_utils.o: c_utils.c
lib_timing.so: c_timing.c
$(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_timing.so $<
+prng.o: prng/prng.c
+ $(CC) $(CFLAGS) -c $<
+
+lib_prng.so: c_prng.c
+ $(CC) -o $@ -shared -Wl,-soname,lib_prng.so $(CFLAGS) $<
+
+c_preload.o: c_preload.c
+ $(CC) $(CFLAGS) -c $<
+
+lib_preload.so: c_preload.o prng.o
+ $(CC) -o $@ -shared $(CFLAGS) -ldl -Wl,-soname,lib_preload.so $^
+
lib_csignals.so: c_signals.c
$(CC) -o $@ -shared $(CFLAGS) -pthread -lpthread -Wl,-soname,lib_csignals.so $<
@@ -83,10 +95,14 @@ cpp_utils.o: cpp_utils.cpp
$(CXX) $(CXXFLAGS) -c $<
+clibs: lib_timing.so lib_csignals.so lib_preload.so lib_prng.so
+
+cpplibs: lib_timing.so lib_cppsignals.so lib_preload.so lib_prng.so
+
# OpenSSL shim
openssl: openssl_provider.so
-openssl_provider.so: openssl.o c_utils.o | lib_timing.so lib_csignals.so
+openssl_provider.so: openssl.o c_utils.o | clibs
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs openssl) -l:lib_timing.so -l:lib_csignals.so
openssl.o: openssl.c
@@ -99,7 +115,7 @@ boringssl: boringssl_provider.so
lib_boringssl.so:
cp $(PROJECT_ROOT_PATH)/ext/boringssl/build/crypto/libcrypto.so lib_boringssl.so
-boringssl_provider.so: boringssl.o c_utils.o | lib_timing.so lib_csignals.so lib_boringssl.so
+boringssl_provider.so: boringssl.o c_utils.o | clibs lib_boringssl.so
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_boringssl.so -l:lib_timing.so -l:lib_csignals.so
boringssl.o: boringssl.c
@@ -109,7 +125,7 @@ boringssl.o: boringssl.c
# libgcrypt shim
gcrypt: gcrypt_provider.so
-gcrypt_provider.so: gcrypt.o c_utils.o | lib_timing.so lib_csignals.so
+gcrypt_provider.so: gcrypt.o c_utils.o | clibs
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -pthread -lpthread $(shell libgcrypt-config --libs) -l:lib_timing.so -l:lib_csignals.so
gcrypt.o: gcrypt.c
@@ -119,7 +135,7 @@ gcrypt.o: gcrypt.c
# Libtomcrypt shim
tomcrypt: tomcrypt_provider.so
-tomcrypt_provider.so: tomcrypt.o c_utils.o | lib_timing.so lib_csignals.so
+tomcrypt_provider.so: tomcrypt.o c_utils.o | clibs
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt) -l:lib_timing.so -l:lib_csignals.so
tomcrypt.o: tomcrypt.c
@@ -129,7 +145,7 @@ tomcrypt.o: tomcrypt.c
# Botan-2 shim
botan: botan_provider.so
-botan_provider.so: botan.o cpp_utils.o | lib_timing.so lib_cppsignals.so
+botan_provider.so: botan.o cpp_utils.o | cpplibs
$(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs botan-2) -l:lib_timing.so -l:lib_cppsignals.so
botan.o: botan.cpp
@@ -143,7 +159,7 @@ ifeq ($(shell pkg-config --exists $(CRYPTOPP_NAME); echo $$?),1)
endif
cryptopp: cryptopp_provider.so
-cryptopp_provider.so: cryptopp.o cpp_utils.o | lib_timing.so lib_cppsignals.so
+cryptopp_provider.so: cryptopp.o cpp_utils.o | cpplibs
$(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs $(CRYPTOPP_NAME)) -l:lib_timing.so -l:lib_cppsignals.so
cryptopp.o: cryptopp.cpp
@@ -156,7 +172,7 @@ mbedtls: mbedtls_provider.so
lib_mbedtls.so:
cp $(PROJECT_ROOT_PATH)/ext/mbedtls/build/library/libmbedcrypto.so lib_mbedtls.so
-mbedtls_provider.so: mbedtls.o c_utils.o | lib_timing.so lib_csignals.so lib_mbedtls.so
+mbedtls_provider.so: mbedtls.o c_utils.o | clibs lib_mbedtls.so
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_mbedtls.so -l:lib_timing.so -l:lib_csignals.so
mbedtls.o: mbedtls.c
@@ -169,7 +185,7 @@ ippcp: ippcp_provider.so
lib_ippcp.so:
cp $(PROJECT_ROOT_PATH)/ext/ipp-crypto/build/.build/RELEASE/lib/libippcp.so lib_ippcp.so
-ippcp_provider.so: ippcp.o c_utils.o | lib_timing.so lib_csignals.so lib_ippcp.so
+ippcp_provider.so: ippcp.o c_utils.o | clibs lib_ippcp.so
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_ippcp.so -l:lib_timing.so -l:lib_csignals.so
ippcp.o: ippcp.c
@@ -179,7 +195,7 @@ ippcp.o: ippcp.c
# Nettle shim
nettle: nettle_provider.so
-nettle_provider.so: nettle.o c_utils.o | lib_timing.so lib_csignals.so
+nettle_provider.so: nettle.o c_utils.o | clibs
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs nettle) -l:lib_timing.so -l:lib_csignals.so $(shell pkg-config --libs hogweed) -lgmp
nettle.o: nettle.c
@@ -192,7 +208,7 @@ libressl: libressl_provider.so
lib_libressl.so:
cp $(PROJECT_ROOT_PATH)/ext/libressl/build/crypto/libcrypto.so lib_libressl.so
-libressl_provider.so: libressl.o c_utils.o | lib_timing.so lib_csignals.so lib_libressl.so
+libressl_provider.so: libressl.o c_utils.o | clibs lib_libressl.so
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_libressl.so -l:lib_timing.so -l:lib_csignals.so
libressl.o: libressl.c
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp
index 52c8dbb..b3977e1 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp
@@ -4,7 +4,9 @@
#include <botan/version.h>
#include <botan/rng.h>
#include <botan/secmem.h>
+#include <botan/system_rng.h>
#include <botan/auto_rng.h>
+#include <botan/chacha_rng.h>
#include <botan/ec_group.h>
#include <botan/ecc_key.h>
@@ -23,7 +25,7 @@
*/
static jclass provider_class;
-static Botan::AutoSeeded_RNG rng;
+std::unique_ptr<Botan::RandomNumberGenerator> rng = std::make_unique<Botan::AutoSeeded_RNG>();
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider(JNIEnv *env, jobject self) {
/* Create the custom provider. */
@@ -82,7 +84,7 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
init_classes(env, "Botan");
}
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self){
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self) {
jclass set_class = env->FindClass("java/util/TreeSet");
jmethodID set_ctr = env->GetMethodID(set_class, "<init>", "()V");
@@ -99,6 +101,25 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurv
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = env->GetArrayLength(seed);
+ if (seed_length < 32) {
+ fprintf(stderr, "Error setting seed, needs to be at least 32 bytes.\n");
+ return JNI_FALSE;
+ }
+ jbyte *seed_data = env->GetByteArrayElements(seed, nullptr);
+ Botan::secure_vector<uint8_t> vec((uint8_t *)seed_data, (uint8_t *)seed_data + seed_length);
+ Botan::ChaCha_RNG *cha = new Botan::ChaCha_RNG(vec);
+ rng.reset(cha);
+ env->ReleaseByteArrayElements(seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported(JNIEnv *env, jobject self, jint keysize){
return JNI_TRUE;
}
@@ -252,13 +273,13 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
try {
native_timing_start();
if (type_str == "ECDH") {
- skey = std::make_unique<Botan::ECDH_PrivateKey>(rng, group);
+ skey = std::make_unique<Botan::ECDH_PrivateKey>(*rng, group);
} else if (type_str == "ECDSA") {
- skey = std::make_unique<Botan::ECDSA_PrivateKey>(rng, group);
+ skey = std::make_unique<Botan::ECDSA_PrivateKey>(*rng, group);
} else if (type_str == "ECKCDSA") {
- skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(rng, group);
+ skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(*rng, group);
} else if (type_str == "ECGDSA") {
- skey = std::make_unique<Botan::ECGDSA_PrivateKey>(rng, group);
+ skey = std::make_unique<Botan::ECGDSA_PrivateKey>(*rng, group);
}
native_timing_stop();
} catch (Botan::Exception & ex) {
@@ -375,7 +396,7 @@ jbyteArray generate_secret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteAr
Botan::BigInt privkey_scalar((unsigned char *) privkey_data, privkey_length);
env->ReleaseByteArrayElements(privkey, privkey_data, JNI_ABORT);
- Botan::ECDH_PrivateKey skey(rng, curve_group, privkey_scalar);
+ Botan::ECDH_PrivateKey skey(*rng, curve_group, privkey_scalar);
jsize pubkey_length = env->GetArrayLength(pubkey);
jbyte *pubkey_data = env->GetByteArrayElements(pubkey, nullptr);
@@ -402,7 +423,7 @@ jbyteArray generate_secret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteAr
size_t key_len = (get_kdf_bits(env, algorithm) + 7) / 8;
std::string kdf = get_kdf(type_str, &key_len);
- Botan::PK_Key_Agreement ka(skey, rng, kdf);
+ Botan::PK_Key_Agreement ka(skey, *rng, kdf);
std::vector<uint8_t> derived;
try {
@@ -469,11 +490,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
std::unique_ptr<Botan::EC_PrivateKey> skey;
try {
if (type_str.find("ECDSA") != std::string::npos) {
- skey = std::make_unique<Botan::ECDSA_PrivateKey>(rng, curve_group, privkey_scalar);
+ skey = std::make_unique<Botan::ECDSA_PrivateKey>(*rng, curve_group, privkey_scalar);
} else if (type_str.find("ECKCDSA") != std::string::npos) {
- skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(rng, curve_group, privkey_scalar);
+ skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(*rng, curve_group, privkey_scalar);
} else if (type_str.find("ECGDSA") != std::string::npos) {
- skey = std::make_unique<Botan::ECGDSA_PrivateKey>(rng, curve_group, privkey_scalar);
+ skey = std::make_unique<Botan::ECGDSA_PrivateKey>(*rng, curve_group, privkey_scalar);
}
} catch (Botan::Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
@@ -504,10 +525,10 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jbyte *data_bytes = env->GetByteArrayElements(data, nullptr);
std::vector<uint8_t> sig;
try {
- Botan::PK_Signer signer(*skey, rng, emsa, sigformat);
+ Botan::PK_Signer signer(*skey, *rng, emsa, sigformat);
native_timing_start();
- sig = signer.sign_message((uint8_t*) data_bytes, data_length, rng);
+ sig = signer.sign_message((uint8_t*) data_bytes, data_length, *rng);
native_timing_stop();
} catch (Botan::Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c
new file mode 100644
index 0000000..1f597a3
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c
@@ -0,0 +1,316 @@
+#define _GNU_SOURCE
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/random.h>
+#include <sys/syscall.h>
+
+#include "native.h"
+#include "prng/prng.h"
+
+
+#ifdef DEBUG_PRELOAD
+
+void print_buf(uint8_t *buf, size_t len) {
+ for (int i = 0; i < len; ++i) {
+ fprintf(stderr, "%02x ", buf[i]);
+ }
+ fprintf(stderr, "\n");
+}
+
+#else
+
+#define print_buf(buf, len)
+
+#endif
+
+typedef int (*open_t)(const char *pathname, int flags, ...);
+static open_t real_open;
+typedef int (*openat_t)(int fd, const char *pathname, int flags, ...);
+static openat_t real_openat;
+typedef ssize_t (*read_t)(int fd, void *buf, size_t count);
+static read_t real_read;
+typedef FILE *(*fopen_t)(const char *pathname, const char *mode);
+static fopen_t real_fopen;
+typedef size_t (*fread_t)(void *ptr, size_t size, size_t nmemb, FILE *stream);
+static fread_t real_fread;
+typedef ssize_t (*getrandom_t)(void *buf, size_t buflen, unsigned int flags);
+static getrandom_t real_getrandom;
+typedef int (*getentropy_t)(void *buffer, size_t length);
+static getentropy_t real_getentropy;
+typedef long (*syscall_t)(long number, ...);
+static syscall_t real_syscall;
+typedef uint32_t (*arc4random_t)(void);
+static arc4random_t real_arc4random;
+typedef uint32_t (*arc4random_uniform_t)(uint32_t upper_bound);
+static arc4random_uniform_t real_arc4random_uniform;
+typedef void (*arc4random_buf_t)(void *buf, size_t n);
+static arc4random_buf_t real_arc4random_buf;
+
+prng_state preload_prng_state;
+bool preload_prng_enabled = false;
+
+static int *random_fds = NULL;
+static size_t random_fds_used = 0;
+static size_t random_fds_allocd = 0;
+
+void check_random_fds() {
+ if (random_fds_allocd == 0) {
+ random_fds_allocd = 10;
+ random_fds = calloc(random_fds_allocd, sizeof(int));
+ } else if (random_fds_allocd == random_fds_used) {
+ random_fds_allocd *= 2;
+ random_fds = realloc(random_fds, random_fds_allocd * sizeof(int));
+ }
+}
+
+void store_random_fd(int fd) {
+ check_random_fds();
+ random_fds[random_fds_used++] = fd;
+}
+
+int open(const char *pathname, int flags, ...) {
+ if (!real_open) {
+ real_open = dlsym(RTLD_NEXT, "open");
+ }
+
+ va_list args;
+ va_start(args, flags);
+ int mode = va_arg(args, int);
+ va_end(args);
+
+ int result = real_open(pathname, flags, mode);
+ if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) {
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called open(%s, %i, %i)\n", pathname, flags, mode);
+#endif
+ store_random_fd(result);
+ }
+ return result;
+}
+
+int openat(int fd, const char *pathname, int flags, ...) {
+ if (!real_openat) {
+ real_openat = dlsym(RTLD_NEXT, "openat");
+ }
+
+ va_list args;
+ va_start(args, flags);
+ int mode = va_arg(args, int);
+ va_end(args);
+
+ int result = real_openat(fd, pathname, flags, mode);
+ if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) {
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called openat(%s, %i, %i)\n", pathname, flags, mode);
+#endif
+ store_random_fd(result);
+ }
+ return result;
+}
+
+ssize_t read(int fd, void *buf, size_t count) {
+ if (!real_read) {
+ real_read = dlsym(RTLD_NEXT, "read");
+ }
+
+ if (preload_prng_enabled) {
+ for (int i = 0; i < random_fds_used; ++i) {
+ int random_fd = random_fds[i];
+ if (random_fd == fd) {
+ prng_get(&preload_prng_state, buf, count);
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "read from random\n");
+ print_buf(buf, count);
+#endif
+ return count;
+ }
+ }
+ }
+
+ return real_read(fd, buf, count);
+}
+
+static FILE **random_files = NULL;
+static size_t random_files_used = 0;
+static size_t random_files_allocd = 0;
+
+void check_random_files() {
+ if (random_files_allocd == 0) {
+ random_files_allocd = 10;
+ random_files = calloc(random_files_allocd, sizeof(FILE *));
+ } else if (random_files_allocd == random_files_used) {
+ random_files_allocd *= 2;
+ random_files = realloc(random_files, random_files_allocd * sizeof(FILE*));
+ }
+}
+
+void store_random_file(FILE *file) {
+ check_random_files();
+ random_files[random_files_used++] = file;
+}
+
+FILE *fopen(const char *pathname, const char *mode) {
+ if (!real_fopen) {
+ real_fopen = dlsym(RTLD_NEXT, "fopen");
+ }
+
+ FILE *result = real_fopen(pathname, mode);
+
+ if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) {
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called fopen(%s, %s)\n", pathname, mode);
+#endif
+ store_random_file(result);
+ }
+ return result;
+}
+
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
+ if (!real_fread) {
+ real_fread = dlsym(RTLD_NEXT, "fread");
+ }
+
+ if (preload_prng_enabled) {
+ for (int i = 0; i < random_files_used; ++i) {
+ FILE *random_file = random_files[i];
+ if (random_file == stream) {
+ prng_get(&preload_prng_state, ptr, size * nmemb);
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "fread from random\n");
+ print_buf(ptr, size * nmemb);
+#endif
+ return size * nmemb;
+ }
+ }
+ }
+
+ return real_fread(ptr, size, nmemb, stream);
+}
+
+ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) {
+ if (!real_getrandom) {
+ real_getrandom = dlsym(RTLD_NEXT, "getrandom");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called getrandom(*, %lu, %u)\n", buflen, flags);
+#endif
+ if (preload_prng_enabled) {
+ prng_get(&preload_prng_state, buf, buflen);
+ print_buf(buf, buflen);
+ return buflen;
+ } else {
+ return real_getrandom(buf, buflen, flags);
+ }
+}
+
+int getentropy(void *buffer, size_t length) {
+ if (!real_getentropy) {
+ real_getentropy = dlsym(RTLD_NEXT, "getentropy");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called getentropy(*, %lu)\n", length);
+#endif
+ if (preload_prng_enabled) {
+ prng_get(&preload_prng_state, buffer, length);
+ print_buf(buffer, length);
+ return 0;
+ } else {
+ return real_getentropy(buffer, length);
+ }
+}
+
+long syscall(long number, ...) {
+ if (!real_syscall) {
+ real_syscall = dlsym(RTLD_NEXT, "syscall");
+ }
+ va_list args;
+
+ va_start(args, number);
+ long int a0 = va_arg(args, long int);
+ long int a1 = va_arg(args, long int);
+ long int a2 = va_arg(args, long int);
+ long int a3 = va_arg(args, long int);
+ long int a4 = va_arg(args, long int);
+ long int a5 = va_arg(args, long int);
+ va_end(args);
+
+ if (number == SYS_getrandom) {
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called syscall(getrandom, %li, %li, %li, %li, %li, %li)\n", a0, a1, a2, a3, a4, a5);
+#endif
+ if (preload_prng_enabled) {
+ uint8_t *buf = (uint8_t*)a0;
+ long n = a1;
+ prng_get(&preload_prng_state, buf, n);
+ print_buf(buf, n);
+ return n;
+ }
+ }
+ return real_syscall(number, a0, a1, a2, a3, a4, a5);
+}
+
+uint32_t arc4random(void) {
+ if (!real_arc4random) {
+ real_arc4random = dlsym(RTLD_NEXT, "arc4random");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called arc4random\n");
+#endif
+ if (preload_prng_enabled) {
+ uint32_t val = 0;
+ prng_get(&preload_prng_state, (uint8_t*)&val, sizeof(val));
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "%u\n", val);
+#endif
+ return val;
+ } else {
+ return real_arc4random();
+ }
+}
+
+uint32_t arc4random_uniform(uint32_t upper_bound) {
+ if (!real_arc4random_uniform) {
+ real_arc4random_uniform = dlsym(RTLD_NEXT, "arc4random_uniform");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called arc4random_uniform(%u)\n", upper_bound);
+#endif
+ if (preload_prng_enabled) {
+ uint64_t val = 0;
+ prng_get(&preload_prng_state, (uint8_t*)&val, sizeof(val));
+ uint32_t result = (uint32_t)(val % (uint64_t)upper_bound);
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "%u\n", result);
+#endif
+ return result;
+ } else {
+ return real_arc4random_uniform(upper_bound);
+ }
+}
+
+void arc4random_buf(void *buf, size_t n) {
+ if (!real_arc4random_buf) {
+ real_arc4random_buf = dlsym(RTLD_NEXT, "arc4random_buf");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called arc4random_buf(%p, %lu) = ", buf, n);
+#endif
+ if (preload_prng_enabled) {
+ prng_get(&preload_prng_state, buf, n);
+ print_buf(buf, n);
+ } else {
+ real_arc4random_buf(buf, n);
+ }
+} \ No newline at end of file
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c
new file mode 100644
index 0000000..13bd172
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c
@@ -0,0 +1,18 @@
+#include <jni.h>
+#include <stdbool.h>
+#include "prng/prng.h"
+
+extern prng_state preload_prng_state;
+extern bool preload_prng_enabled;
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+
+ preload_prng_enabled = true;
+ prng_init(&preload_prng_state);
+ prng_seed(&preload_prng_state, seed_data, seed_length);
+
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+} \ No newline at end of file
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
index c4c74a6..1f82f8a 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
@@ -22,8 +22,12 @@ using CryptoPP::Exception;
using CryptoPP::byte;
#include "cryptopp/osrng.h"
+using CryptoPP::RandomNumberGenerator;
using CryptoPP::AutoSeededRandomPool;
+#include "cryptopp/mersenne.h"
+using CryptoPP::MT19937;
+
#include "cryptopp/sha.h"
using CryptoPP::SHA1;
using CryptoPP::SHA224;
@@ -89,7 +93,7 @@ using CryptoPP::Integer;
*/
static jclass provider_class;
-static AutoSeededRandomPool rng;
+static std::unique_ptr<RandomNumberGenerator> rng = std::make_unique<AutoSeededRandomPool>();
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider(JNIEnv *env, jobject self) {
@@ -187,6 +191,23 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getC
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = env->GetArrayLength(seed);
+ if (seed_length > 4) {
+ fprintf(stderr, "Error setting seed, needs to be at most 4 bytes.\n");
+ return JNI_FALSE;
+ }
+ jbyte *seed_data = env->GetByteArrayElements(seed, nullptr);
+ uint32_t seed_int = seed_data[0] | seed_data[1] << 8 | seed_data[2] << 16 | seed_data[3] << 24;
+ rng.reset(new MT19937(seed_int));
+ env->ReleaseByteArrayElements(seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
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 & ecp_oid : ecp_oids) {
@@ -517,7 +538,7 @@ template <class EC> jobject generate_from_group(JNIEnv *env, DL_GroupParameters_
SIG_TRY(TIMEOUT) {
try {
native_timing_start();
- ec_domain.GenerateKeyPair(rng, priv, pub);
+ ec_domain.GenerateKeyPair(*rng, priv, pub);
native_timing_stop();
} catch (Exception & ex) {
SIG_DEINIT();
@@ -661,7 +682,7 @@ jbyteArray sign_message(JNIEnv *env, DL_GroupParameters_EC<EC> group, jbyteArray
size_t len;
SIG_TRY(TIMEOUT) {
native_timing_start();
- len = signer.SignMessage(rng, (byte *)data_bytes, data_length, (byte *)signature.c_str());
+ len = signer.SignMessage(*rng, (byte *)data_bytes, data_length, (byte *)signature.c_str());
native_timing_stop();
} SIG_CATCH_HANDLE(env);
env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
index 795c30a..40376f9 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
@@ -25,6 +25,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_create
jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V");
+ gcry_control(GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
const char *running_with = gcry_check_version(GCRYPT_VERSION);
if (!running_with) {
return NULL;
@@ -40,9 +41,8 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_create
JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Gcrypt_setup(JNIEnv *env, jobject this) {
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
- //gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 1);
- gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+ //gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 1);
INIT_PROVIDER(env, provider_class);
@@ -651,4 +651,4 @@ release_init:
gcry_sexp_release(pub_sexp);
gcry_sexp_release(data_sexp);
return result;
-} \ No newline at end of file
+}
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c
index fbf917e..86f0f7e 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c
@@ -136,6 +136,29 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_getCurv
return result;
}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ if (seed_length % 4 != 0) {
+ fprintf(stderr, "Error setting seed, needs to be a multiple of 4 bytes.\n");
+ return JNI_FALSE;
+ }
+ int bn_size;
+ ippsBigNumGetSize(seed_length / 4, &bn_size);
+ uint8_t bn_buf[bn_size];
+ IppsBigNumState *bn = (IppsBigNumState *)bn_buf;
+ ippsBigNumInit(seed_length / 4, bn);
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ ippsSet_BN(IppsBigNumPOS, seed_length / 4, (Ipp32u *) seed_data, bn);
+ ippsPRNGSetSeed(bn, prng_state);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Ippcp_keysizeSupported(JNIEnv *env,
jobject this,
jint keysize) {
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
index 5fc879b..8f5e0fb 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
@@ -16,7 +16,8 @@
static mbedtls_ctr_drbg_context ctr_drbg;
-static mbedtls_entropy_context entropy;
+static mbedtls_entropy_context urandom_entropy;
+static mbedtls_entropy_context fixed_entropy;
static jclass provider_class;
@@ -62,6 +63,17 @@ static int dev_urandom(void *data, unsigned char *output, size_t len, size_t *ol
return 0;
}
+static unsigned char seed_store[32] = {0};
+
+static int fixed_random(void *data, unsigned char *output, size_t len, size_t *olen) {
+ for (size_t i = 0; i < len; ++i) {
+ output[i] = seed_store[i % 32];
+ }
+ *olen = len;
+ return 0;
+}
+
+
static int ctr_drbg_wrapper(void *ctx, unsigned char *buf, size_t len) {
native_timing_pause();
int result = mbedtls_ctr_drbg_random(ctx, buf, len);
@@ -77,9 +89,9 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
ADD_SIG(env, this, "NONEwithECDSA", "MbedTLSECDSAwithNONE");
mbedtls_ctr_drbg_init(&ctr_drbg);
- mbedtls_entropy_init(&entropy);
- mbedtls_entropy_add_source(&entropy, dev_urandom, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);
- mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
+ mbedtls_entropy_init(&urandom_entropy);
+ mbedtls_entropy_add_source(&urandom_entropy, dev_urandom, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);
+ mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &urandom_entropy, NULL, 0);
init_classes(env, "MbedTLS");
}
@@ -101,6 +113,32 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getCu
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_supportsDeterministicPRNG(JNIEnv *env, jobject this) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_setupDeterministicPRNG(JNIEnv *env, jobject this, jbyteArray seed) {
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ if (seed_length > 32) {
+ fprintf(stderr, "Error setting seed, needs to be at most 32 bytes, is %i.\n", seed_length);
+ return JNI_FALSE;
+ }
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ memcpy(seed_store, seed_data, seed_length);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+
+ memset(&ctr_drbg, 0, sizeof(ctr_drbg));
+ mbedtls_ctr_drbg_init(&ctr_drbg);
+
+ mbedtls_entropy_init(&fixed_entropy);
+ // This is NASTY! We are accessing something the library does not want us to.
+ fixed_entropy.private_source_count = 0;
+ mbedtls_entropy_add_source(&fixed_entropy, fixed_random, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);
+ mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &fixed_entropy, NULL, 0);
+
+ return JNI_TRUE;
+}
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_keysizeSupported(JNIEnv *env, jobject this, jint keysize) {
for (const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_list();
curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h
index 60c59b1..881243f 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -47,6 +47,14 @@ JNIEXPORT jstring JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_
JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_getLastNativeTiming
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_NativeECLibrary
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -74,6 +82,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_crea
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -255,6 +279,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createP
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -436,6 +476,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_crea
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -617,6 +673,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_creat
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -1341,6 +1413,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_creat
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -1522,6 +1610,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_createP
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_getCurves
(JNIEnv *, jobject);
+/*
+* Class: cz_crcs_ectester_standalone_libs_IppcpLib
+* Method: supportsDeterministicPRNG
+* Signature: ()Z
+*/
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_supportsDeterministicPRNG
+(JNIEnv *, jobject);
+
+/*
+* Class: cz_crcs_ectester_standalone_libs_IppcpLib
+* Method: setupDeterministicPRNG
+* Signature: ([B)Z
+*/
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_setupDeterministicPRNG
+(JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -1884,6 +1988,21 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_create
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCurves
(JNIEnv *, jobject);
+/*
+* Class: cz_crcs_ectester_standalone_libs_NettleLib
+* Method: supportsDeterministicPRNG
+* Signature: ()Z
+*/
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_supportsDeterministicPRNG
+(JNIEnv *, jobject);
+
+/*
+* Class: cz_crcs_ectester_standalone_libs_NettleLib
+* Method: setupDeterministicPRNG
+* Signature: ([B)Z
+*/
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_setupDeterministicPRNG
+(JNIEnv *, jobject, jbyteArray);
#ifdef __cplusplus
}
#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c
index e7ec00e..08b09d5 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c
@@ -44,10 +44,16 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
init_classes(env, "Nettle");
yarrow256_init(&yarrow, 0, NULL);
- uint8_t file = open("/dev/random", O_RDONLY);
- yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, &file);
- close(file);
-
+ FILE *urandom = fopen("/dev/urandom", "rb");
+ uint8_t seed[YARROW256_SEED_FILE_SIZE];
+ if (urandom) {
+ size_t read = 0;
+ while (read < sizeof(seed)) {
+ read += fread(((uint8_t *)&seed) + read, 1, sizeof(seed) - read, urandom);
+ }
+ fclose(urandom);
+ }
+ yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, seed);
}
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCurves(JNIEnv *env, jobject self) {
@@ -66,6 +72,24 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCur
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ if (seed_length < YARROW256_SEED_FILE_SIZE) {
+ fprintf(stderr, "Error setting seed, needs to be at least %i bytes.\n", YARROW256_SEED_FILE_SIZE);
+ return JNI_FALSE;
+ }
+
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ yarrow256_init(&yarrow, 0, NULL);
+ yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, seed_data);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
static const struct ecc_curve* create_curve_from_name(JNIEnv *env, const char* curve_name) {
if (!curve_name) {
return NULL;
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c
index 59eb0db..5110c8b 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c
@@ -14,6 +14,7 @@
#include <openssl/err.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
+#include <openssl/rand.h>
@@ -69,6 +70,58 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCu
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+static int stdlib_rand_seed(const void *buf, int num)
+{
+ unsigned int s = 0;
+ for (int i = 0; i < num && i < sizeof(unsigned int); ++i) {
+ s |= ((unsigned char*)buf)[i] << 8*i;
+ }
+ srand(s);
+ return 1;
+}
+
+// Fill the buffer with random bytes. For each byte in the buffer, we generate
+// a random number and clamp it to the range of a byte, 0-255.
+static int stdlib_rand_bytes(unsigned char *buf, int num)
+{
+ for (int index = 0; index < num; ++index)
+ {
+ buf[index] = rand() % 256;
+ }
+ return 1;
+}
+
+static void stdlib_rand_cleanup() {}
+static int stdlib_rand_add(const void *buf, int num, double add_entropy)
+{
+ return 1;
+}
+static int stdlib_rand_status()
+{
+ return 1;
+}
+
+RAND_METHOD stdlib_rand_meth = { stdlib_rand_seed,
+ stdlib_rand_bytes,
+ stdlib_rand_cleanup,
+ stdlib_rand_add,
+ stdlib_rand_bytes,
+ stdlib_rand_status
+};
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ RAND_set_rand_method(&stdlib_rand_meth);
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ RAND_seed(seed_data, seed_length);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
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];
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h
new file mode 100644
index 0000000..6371611
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h
@@ -0,0 +1,37 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakDuplexCommon_h_
+#define _KeccakDuplexCommon_h_
+
+#include "align.h"
+
+#define KCP_DeclareDuplexStructure(prefix, size, alignment) \
+ ALIGN(alignment) typedef struct prefix##_DuplexInstanceStruct { \
+ unsigned char state[size]; \
+ unsigned int rate; \
+ unsigned int byteInputIndex; \
+ unsigned int byteOutputIndex; \
+ } prefix##_DuplexInstance;
+
+#define KCP_DeclareDuplexFunctions(prefix) \
+ int prefix##_DuplexInitialize(prefix##_DuplexInstance *duplexInstance, unsigned int rate, unsigned int capacity); \
+ int prefix##_Duplexing(prefix##_DuplexInstance *duplexInstance, const unsigned char *sigmaBegin, unsigned int sigmaBeginByteLen, unsigned char *Z, unsigned int ZByteLen, unsigned char delimitedSigmaEnd); \
+ int prefix##_DuplexingFeedPartialInput(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned int inputByteLen); \
+ int prefix##_DuplexingFeedZeroes(prefix##_DuplexInstance *duplexInstance, unsigned int inputByteLen); \
+ int prefix##_DuplexingOverwritePartialInput(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned int inputByteLen); \
+ int prefix##_DuplexingOverwriteWithZeroes(prefix##_DuplexInstance *duplexInstance, unsigned int inputByteLen); \
+ int prefix##_DuplexingGetFurtherOutput(prefix##_DuplexInstance *duplexInstance, unsigned char *out, unsigned int outByteLen); \
+ int prefix##_DuplexingGetFurtherOutputAndAdd(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned char *output, unsigned int outputByteLen);
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc
new file mode 100644
index 0000000..bd58043
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc
@@ -0,0 +1,192 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#define JOIN0(a, b) a ## b
+#define JOIN(a, b) JOIN0(a, b)
+
+#define DuplexInstance JOIN(prefix, _DuplexInstance)
+#define DuplexInitialize JOIN(prefix, _DuplexInitialize)
+#define Duplexing JOIN(prefix, _Duplexing)
+#define DuplexingFeedPartialInput JOIN(prefix, _DuplexingFeedPartialInput)
+#define DuplexingFeedZeroes JOIN(prefix, _DuplexingFeedZeroes)
+#define DuplexingOverwritePartialInput JOIN(prefix, _DuplexingOverwritePartialInput)
+#define DuplexingOverwriteWithZeroes JOIN(prefix, _DuplexingOverwriteWithZeroes)
+#define DuplexingGetFurtherOutput JOIN(prefix, _DuplexingGetFurtherOutput)
+#define DuplexingGetFurtherOutputAndAdd JOIN(prefix, _DuplexingGetFurtherOutputAndAdd)
+
+#define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes)
+#define SnP_stateAlignment JOIN(SnP, _stateAlignment)
+#define SnP_StaticInitialize JOIN(SnP, _StaticInitialize)
+#define SnP_Initialize JOIN(SnP, _Initialize)
+#define SnP_AddByte JOIN(SnP, _AddByte)
+#define SnP_AddBytes JOIN(SnP, _AddBytes)
+#define SnP_OverwriteBytes JOIN(SnP, _OverwriteBytes)
+#define SnP_OverwriteWithZeroes JOIN(SnP, _OverwriteWithZeroes)
+#define SnP_ExtractBytes JOIN(SnP, _ExtractBytes)
+#define SnP_ExtractAndAddBytes JOIN(SnP, _ExtractAndAddBytes)
+
+int DuplexInitialize(DuplexInstance *instance, unsigned int rate, unsigned int capacity)
+{
+ if (rate+capacity != SnP_width)
+ return 1;
+ if ((rate <= 2) || (rate > SnP_width))
+ return 1;
+ SnP_StaticInitialize();
+ instance->rate = rate;
+ SnP_Initialize(instance->state);
+ instance->byteInputIndex = 0;
+ instance->byteOutputIndex = (instance->rate+7)/8;
+ return 0;
+}
+
+int Duplexing(DuplexInstance *instance, const unsigned char *sigmaBegin, unsigned int sigmaBeginByteLen, unsigned char *Z, unsigned int ZByteLen, unsigned char delimitedSigmaEnd)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if (delimitedSigmaEnd == 0)
+ return 1;
+ if ((instance->byteInputIndex+sigmaBeginByteLen)*8 > rho_max)
+ return 1;
+ if (rho_max - sigmaBeginByteLen*8 < 7) {
+ unsigned int maxBitsInDelimitedSigmaEnd = rho_max - sigmaBeginByteLen*8;
+ if (delimitedSigmaEnd >= (1 << (maxBitsInDelimitedSigmaEnd+1)))
+ return 1;
+ }
+ if (ZByteLen > (instance->rate+7)/8)
+ return 1; /* The output length must not be greater than the rate (rounded up to a byte) */
+
+ SnP_AddBytes(instance->state, sigmaBegin, instance->byteInputIndex, sigmaBeginByteLen);
+ #ifdef KeccakReference
+ {
+ unsigned char block[SnP_width/8];
+ memcpy(block, sigmaBegin, sigmaBeginByteLen);
+ block[sigmaBeginByteLen] = delimitedSigmaEnd;
+ memset(block+sigmaBeginByteLen+1, 0, sizeof(block)-sigmaBeginByteLen-1);
+ block[(instance->rate-1)/8] |= 1 << ((instance->rate-1) % 8);
+ displayBytes(1, "Block to be absorbed (after padding)", block, (instance->rate+7)/8);
+ }
+ #endif
+
+ /* Last few bits, whose delimiter coincides with first bit of padding */
+ SnP_AddByte(instance->state, delimitedSigmaEnd, instance->byteInputIndex+sigmaBeginByteLen);
+ /* Second bit of padding */
+ SnP_AddByte(instance->state, (unsigned char)1 << ((instance->rate - 1)%8), (instance->rate - 1)/8);
+ SnP_Permute(instance->state);
+ SnP_ExtractBytes(instance->state, Z, 0, ZByteLen);
+
+ if (ZByteLen*8 > instance->rate) {
+ unsigned char mask = (unsigned char)(1 << (instance->rate % 8)) - 1;
+ Z[ZByteLen-1] &= mask;
+ }
+
+ instance->byteInputIndex = 0;
+ instance->byteOutputIndex = ZByteLen;
+
+ return 0;
+}
+
+int DuplexingFeedPartialInput(DuplexInstance *instance, const unsigned char *input, unsigned int inputByteLen)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if ((instance->byteInputIndex+inputByteLen)*8 > rho_max)
+ return 1;
+
+ SnP_AddBytes(instance->state, input, instance->byteInputIndex, inputByteLen);
+ instance->byteInputIndex += inputByteLen;
+ return 0;
+}
+
+int DuplexingFeedZeroes(DuplexInstance *instance, unsigned int inputByteLen)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if ((instance->byteInputIndex+inputByteLen)*8 > rho_max)
+ return 1;
+
+ instance->byteInputIndex += inputByteLen;
+ return 0;
+}
+
+int DuplexingOverwritePartialInput(DuplexInstance *instance, const unsigned char *input, unsigned int inputByteLen)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if ((instance->byteInputIndex+inputByteLen)*8 > rho_max)
+ return 1;
+
+ SnP_OverwriteBytes(instance->state, input, instance->byteInputIndex, inputByteLen);
+ instance->byteInputIndex += inputByteLen;
+ return 0;
+}
+
+int DuplexingOverwriteWithZeroes(DuplexInstance *instance, unsigned int inputByteLen)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if ((instance->byteInputIndex != 0) || (inputByteLen*8 > rho_max))
+ return 1;
+
+ SnP_OverwriteWithZeroes(instance->state, inputByteLen);
+ instance->byteInputIndex = inputByteLen;
+
+ return 0;
+}
+
+int DuplexingGetFurtherOutput(DuplexInstance *instance, unsigned char *output, unsigned int outputByteLen)
+{
+ if ((outputByteLen+instance->byteOutputIndex) > (instance->rate+7)/8)
+ return 1; /* The output length must not be greater than the rate (rounded up to a byte) */
+
+ SnP_ExtractBytes(instance->state, output, instance->byteOutputIndex, outputByteLen);
+ instance->byteOutputIndex += outputByteLen;
+ if (instance->byteOutputIndex*8 > instance->rate) {
+ unsigned char mask = (1 << (instance->rate % 8)) - 1;
+ output[outputByteLen-1] &= mask;
+ }
+ return 0;
+}
+
+int DuplexingGetFurtherOutputAndAdd(DuplexInstance *instance, const unsigned char *input, unsigned char *output, unsigned int outputByteLen)
+{
+ if ((outputByteLen+instance->byteOutputIndex) > (instance->rate+7)/8)
+ return 1; /* The output length must not be greater than the rate (rounded up to a byte) */
+
+ SnP_ExtractAndAddBytes(instance->state, input, output, instance->byteOutputIndex, outputByteLen);
+ instance->byteOutputIndex += outputByteLen;
+ if (instance->byteOutputIndex*8 > instance->rate) {
+ unsigned char mask = (1 << (instance->rate % 8)) - 1;
+ output[outputByteLen-1] &= mask;
+ }
+ return 0;
+}
+
+#undef DuplexInstance
+#undef DuplexInitialize
+#undef Duplexing
+#undef DuplexingFeedPartialInput
+#undef DuplexingFeedZeroes
+#undef DuplexingOverwritePartialInput
+#undef DuplexingOverwriteWithZeroes
+#undef DuplexingGetFurtherOutput
+#undef DuplexingGetFurtherOutputAndAdd
+#undef SnP_stateSizeInBytes
+#undef SnP_stateAlignment
+#undef SnP_StaticInitialize
+#undef SnP_Initialize
+#undef SnP_AddByte
+#undef SnP_AddBytes
+#undef SnP_OverwriteBytes
+#undef SnP_OverwriteWithZeroes
+#undef SnP_ExtractBytes
+#undef SnP_ExtractAndAddBytes
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c
new file mode 100644
index 0000000..d6f56d2
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c
@@ -0,0 +1,29 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#include "KeccakDuplexWidth200.h"
+
+#ifndef KeccakP200_excluded
+ #include "KeccakP-200-SnP.h"
+
+ #define prefix KeccakWidth200
+ #define SnP KeccakP200
+ #define SnP_width 200
+ #define SnP_Permute KeccakP200_Permute_18rounds
+ #include "KeccakDuplex.inc"
+ #undef prefix
+ #undef SnP
+ #undef SnP_width
+ #undef SnP_Permute
+ #undef SnP_FastLoop_Absorb
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h
new file mode 100644
index 0000000..8bb76f4
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h
@@ -0,0 +1,25 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakDuplexWidth200_h_
+#define _KeccakDuplexWidth200_h_
+
+#include "KeccakDuplex-common.h"
+
+#ifndef KeccakP200_excluded
+ #include "KeccakP-200-SnP.h"
+ KCP_DeclareDuplexStructure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment)
+ KCP_DeclareDuplexFunctions(KeccakWidth200)
+#endif
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h
new file mode 100644
index 0000000..4acf932
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h
@@ -0,0 +1,34 @@
+/*
+Implementation by Ronny Van Keer, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+
+---
+
+Please refer to SnP-documentation.h for more details.
+*/
+
+#ifndef _KeccakP_200_SnP_h_
+#define _KeccakP_200_SnP_h_
+
+#define KeccakP200_implementation "8-bit compact implementation"
+#define KeccakP200_stateSizeInBytes 25
+#define KeccakP200_stateAlignment 1
+
+#define KeccakP200_StaticInitialize()
+void KeccakP200_Initialize(void *state);
+void KeccakP200_AddByte(void *state, unsigned char data, unsigned int offset);
+void KeccakP200_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
+void KeccakP200_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
+void KeccakP200_OverwriteWithZeroes(void *state, unsigned int byteCount);
+void KeccakP200_Permute_Nrounds(void *state, unsigned int nrounds);
+void KeccakP200_Permute_18rounds(void *state);
+void KeccakP200_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length);
+void KeccakP200_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c
new file mode 100644
index 0000000..f07bae9
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c
@@ -0,0 +1,187 @@
+/*
+Implementation by Ronny Van Keer, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+
+---
+
+This file implements Keccak-p[200] in a SnP-compatible way.
+Please refer to SnP-documentation.h for more details.
+
+This implementation comes with KeccakP-200-SnP.h in the same folder.
+Please refer to LowLevel.build for the exact list of other files it must be combined with.
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include "KeccakP-200-SnP.h"
+
+// #define DIVISION_INSTRUCTION /* comment if no division instruction or more compact when not using division */
+#define UNROLL_CHILOOP /* comment if more compact using for loop */
+
+typedef unsigned char UINT8;
+typedef unsigned int tSmallUInt; /*INFO It could be more optimized to use "unsigned char" on an 8-bit CPU */
+typedef UINT8 tKeccakLane;
+
+#define ROL8(a, offset) (UINT8)((((UINT8)a) << (offset&7)) ^ (((UINT8)a) >> (8-(offset&7))))
+
+const UINT8 KeccakP200_RotationConstants[25] =
+{
+ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
+};
+
+const UINT8 KeccakP200_PiLane[25] =
+{
+ 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
+};
+
+#if defined(DIVISION_INSTRUCTION)
+#define MOD5(argValue) ((argValue) % 5)
+#else
+const UINT8 KeccakP200_Mod5[10] =
+{
+ 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
+};
+#define MOD5(argValue) KeccakP200_Mod5[argValue]
+#endif
+
+const UINT8 KeccakF200_RoundConstants[] =
+{
+ 0x01, 0x82, 0x8a, 0x00, 0x8b, 0x01, 0x81, 0x09, 0x8a, 0x88, 0x09, 0x0a, 0x8b, 0x8b, 0x89, 0x03, 0x02, 0x80
+};
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_Initialize(void *argState)
+{
+ memset( argState, 0, 25 * sizeof(tKeccakLane) );
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_AddByte(void *argState, unsigned char byte, unsigned int offset)
+{
+ ((tKeccakLane*)argState)[offset] ^= byte;
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_AddBytes(void *argState, const unsigned char *data, unsigned int offset, unsigned int length)
+{
+ tSmallUInt i;
+ tKeccakLane * state = (tKeccakLane*)argState + offset;
+ for(i=0; i<length; i++)
+ state[i] ^= data[i];
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
+{
+ memcpy((unsigned char*)state+offset, data, length);
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_OverwriteWithZeroes(void *state, unsigned int byteCount)
+{
+ memset(state, 0, byteCount);
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_Permute_Nrounds(void *argState, unsigned int nr)
+{
+ tSmallUInt x, y;
+ tKeccakLane temp;
+ tKeccakLane BC[5];
+ tKeccakLane *state;
+ const tKeccakLane *rc;
+
+ state = (tKeccakLane*)argState;
+ rc = KeccakF200_RoundConstants + 18 - nr;
+ do
+ {
+ /* Theta */
+ for ( x = 0; x < 5; ++x )
+ {
+ BC[x] = state[x] ^ state[5 + x] ^ state[10 + x] ^ state[15 + x] ^ state[20 + x];
+ }
+ for ( x = 0; x < 5; ++x )
+ {
+ temp = BC[MOD5(x+4)] ^ ROL8(BC[MOD5(x+1)], 1);
+ for ( y = 0; y < 25; y += 5 )
+ {
+ state[y + x] ^= temp;
+ }
+ }
+
+ /* Rho Pi */
+ temp = state[1];
+ for ( x = 0; x < 24; ++x )
+ {
+ BC[0] = state[KeccakP200_PiLane[x]];
+ state[KeccakP200_PiLane[x]] = ROL8( temp, KeccakP200_RotationConstants[x] );
+ temp = BC[0];
+ }
+
+ /* Chi */
+ for ( y = 0; y < 25; y += 5 )
+ {
+#if defined(UNROLL_CHILOOP)
+ BC[0] = state[y + 0];
+ BC[1] = state[y + 1];
+ BC[2] = state[y + 2];
+ BC[3] = state[y + 3];
+ BC[4] = state[y + 4];
+#else
+ for ( x = 0; x < 5; ++x )
+ {
+ BC[x] = state[y + x];
+ }
+#endif
+ for ( x = 0; x < 5; ++x )
+ {
+ state[y + x] = BC[x] ^((~BC[MOD5(x+1)]) & BC[MOD5(x+2)]);
+ }
+ }
+
+ /* Iota */
+ temp = *(rc++);
+ state[0] ^= temp;
+ }
+ while( temp != 0x80 );
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_Permute_18rounds(void *argState)
+{
+ KeccakP200_Permute_Nrounds(argState, 18);
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length)
+{
+ if (length) {
+ memcpy(data, (UINT8*)state+offset, length);
+ }
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_ExtractAndAddBytes(const void *argState, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length)
+{
+ unsigned int i;
+ tKeccakLane * state = (tKeccakLane*)argState + offset;
+ for(i=0; i<length; i++)
+ output[i] = input[i] ^ state[i];
+}
+
+/* ---------------------------------------------------------------- */
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h
new file mode 100644
index 0000000..eca5d2e
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h
@@ -0,0 +1,28 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakPRGCommon_h_
+#define _KeccakPRGCommon_h_
+
+#include "align.h"
+
+#define KCP_DeclareSpongePRG_Structure(prefix, size, alignment) \
+ ALIGN(alignment) typedef struct prefix##_SpongePRG_InstanceStruct { \
+ prefix##_DuplexInstance duplex; \
+ } prefix##_SpongePRG_Instance;
+
+#define KCP_DeclareSpongePRG_Functions(prefix) \
+ int prefix##_SpongePRG_Initialize(prefix##_SpongePRG_Instance *instance, unsigned int capacity); \
+ int prefix##_SpongePRG_Feed(prefix##_SpongePRG_Instance *instance, const unsigned char *input, unsigned int inputByteLen); \
+ int prefix##_SpongePRG_Fetch(prefix##_SpongePRG_Instance *Instance, unsigned char *out, unsigned int outByteLen); \
+ int prefix##_SpongePRG_Forget(prefix##_SpongePRG_Instance *instance);
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h
new file mode 100644
index 0000000..83a2144
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h
@@ -0,0 +1,20 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakPRG_h_
+#define _KeccakPRG_h_
+
+/* For the documentation, please follow the link: */
+/* #include "KeccakPRG-documentation.h" */
+
+#include "KeccakPRGWidth200.h"
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc
new file mode 100644
index 0000000..aa65db0
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc
@@ -0,0 +1,123 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#define JOIN0(a, b) a ## b
+#define JOIN(a, b) JOIN0(a, b)
+
+#define SpongePRG_Instance JOIN(prefix, _SpongePRG_Instance)
+#define SpongePRG_Initialize JOIN(prefix, _SpongePRG_Initialize)
+#define SpongePRG_Feed JOIN(prefix, _SpongePRG_Feed)
+#define SpongePRG_Fetch JOIN(prefix, _SpongePRG_Fetch)
+#define SpongePRG_Forget JOIN(prefix, _SpongePRG_Forget)
+
+#define DuplexInstance JOIN(prefix, _DuplexInstance)
+#define DuplexInitialize JOIN(prefix, _DuplexInitialize)
+#define Duplexing JOIN(prefix, _Duplexing)
+#define DuplexingFeedPartialInput JOIN(prefix, _DuplexingFeedPartialInput)
+#define DuplexingOverwriteWithZeroes JOIN(prefix, _DuplexingOverwriteWithZeroes)
+#define DuplexingGetFurtherOutput JOIN(prefix, _DuplexingGetFurtherOutput)
+#define DuplexGetInputIndex(duplex) (duplex)->byteInputIndex
+#define DuplexGetOutputIndex(duplex) (duplex)->byteOutputIndex
+#define DuplexSetOutputIndex(duplex, i) (duplex)->byteOutputIndex = (i)
+
+int SpongePRG_Initialize(SpongePRG_Instance *instance, unsigned int capacity)
+{
+ unsigned int rate;
+ unsigned int rhoInBytes;
+
+ if (capacity > (SnP_width-10))
+ return 1;
+
+ rate = SnP_width - capacity;
+ rhoInBytes = (rate-2)/8;
+
+ if ( (rhoInBytes == 0) || (rhoInBytes >= SnP_width/8) )
+ return 1;
+ return DuplexInitialize(&instance->duplex, rate, capacity);
+}
+
+int SpongePRG_Feed(SpongePRG_Instance *instance, const unsigned char *input, unsigned int inputByteLen)
+{
+ unsigned int rhoInBytes = (instance->duplex.rate-2)/8;
+ int error = 0;
+
+ while( !error && ((DuplexGetInputIndex(&instance->duplex) + inputByteLen) >= rhoInBytes)) {
+ unsigned int localSize = rhoInBytes - DuplexGetInputIndex(&instance->duplex);
+ error |= DuplexingFeedPartialInput(&instance->duplex, input, localSize);
+ error |= Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01);
+ input += localSize;
+ inputByteLen -= localSize;
+ }
+ if (!error)
+ error = DuplexingFeedPartialInput(&instance->duplex, input, inputByteLen);
+ DuplexSetOutputIndex(&instance->duplex, rhoInBytes);
+ return error;
+}
+
+int SpongePRG_Fetch(SpongePRG_Instance *instance, unsigned char *output, unsigned int outputByteLen)
+{
+ unsigned int rhoInBytes = (instance->duplex.rate-2)/8;
+ int error = 0;
+
+ if (DuplexGetOutputIndex(&instance->duplex) < rhoInBytes) {
+ unsigned int localSize = rhoInBytes - DuplexGetOutputIndex(&instance->duplex);
+ localSize = (localSize <= outputByteLen) ? localSize : outputByteLen;
+ error = DuplexingGetFurtherOutput(&instance->duplex, output, localSize);
+ output += localSize;
+ outputByteLen -= localSize;
+ }
+
+ while( !error && (outputByteLen > 0) ) {
+ error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01);
+ if (!error) {
+ unsigned int localSize = (rhoInBytes <= outputByteLen) ? rhoInBytes : outputByteLen;
+ error = DuplexingGetFurtherOutput(&instance->duplex, output, localSize);
+ output += localSize;
+ outputByteLen -= localSize;
+ }
+ }
+ return error;
+}
+
+int SpongePRG_Forget(SpongePRG_Instance *instance)
+{
+ unsigned int rhoInBytes = (instance->duplex.rate-2)/8;
+ unsigned int capacity = SnP_width - instance->duplex.rate;
+ int error;
+
+ if ((rhoInBytes*8) < capacity)
+ return 1;
+
+ error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01);
+ if ( !error ) {
+ error = DuplexingOverwriteWithZeroes(&instance->duplex, rhoInBytes);
+ if ( !error )
+ error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01);
+ }
+ DuplexSetOutputIndex(&instance->duplex, rhoInBytes);
+ return error;
+}
+
+#undef SpongePRG_Instance
+#undef SpongePRG_Initialize
+#undef SpongePRG_Feed
+#undef SpongePRG_Fetch
+#undef SpongePRG_Forget
+
+#undef DuplexInstance
+#undef DuplexInitialize
+#undef Duplexing
+#undef DuplexingFeedPartialInput
+#undef DuplexingOverwriteWithZeroes
+#undef DuplexingGetFurtherOutput
+#undef DuplexGetInputIndex
+#undef DuplexGetOutputIndex
+#undef DuplexSetOutputIndex
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c
new file mode 100644
index 0000000..067375e
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c
@@ -0,0 +1,22 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#include "KeccakPRGWidth200.h"
+
+#ifndef KeccakP200_excluded
+ #include "KeccakP-200-SnP.h"
+
+ #define prefix KeccakWidth200
+ #define SnP_width 200
+ #include "KeccakPRG.inc"
+ #undef prefix
+ #undef SnP_width
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h
new file mode 100644
index 0000000..d7cfcc9
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h
@@ -0,0 +1,24 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakPRGWidth200_h_
+#define _KeccakPRGWidth200_h_
+
+#include "KeccakDuplexWidth200.h"
+#include "KeccakPRG-common.h"
+
+#ifndef KeccakP200_excluded
+ #include "KeccakP-200-SnP.h"
+ KCP_DeclareSpongePRG_Structure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment)
+ KCP_DeclareSpongePRG_Functions(KeccakWidth200)
+#endif
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h
new file mode 100644
index 0000000..90c1b37
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h
@@ -0,0 +1,32 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _align_h_
+#define _align_h_
+
+/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */
+#ifdef ALIGN
+#undef ALIGN
+#endif
+
+#if defined(__GNUC__)
+#define ALIGN(x) __attribute__ ((aligned(x)))
+#elif defined(_MSC_VER)
+#define ALIGN(x) __declspec(align(x))
+#elif defined(__ARMCC_VERSION)
+#define ALIGN(x) __align(x)
+#else
+#define ALIGN(x)
+#endif
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c
new file mode 100644
index 0000000..c44db6f
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c
@@ -0,0 +1,21 @@
+#include "KeccakPRG.h"
+#include "KeccakP-200-compact.c"
+#include "KeccakDuplexWidth200.c"
+#include "KeccakPRGWidth200.c"
+#include "prng.h"
+#include <stdlib.h>
+
+
+void prng_init(prng_state *state) {
+ memset(state, 0, sizeof(state));
+ KeccakWidth200_SpongePRG_Initialize(state, 70);
+}
+
+void prng_seed(prng_state *state, const uint8_t *seed, size_t size) {
+ KeccakWidth200_SpongePRG_Feed(state, seed, size);
+ KeccakWidth200_SpongePRG_Forget(state);
+}
+
+void prng_get(prng_state *state, uint8_t *out, size_t size) {
+ KeccakWidth200_SpongePRG_Fetch(state, out, size);
+} \ No newline at end of file
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h
new file mode 100644
index 0000000..2cc4f21
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h
@@ -0,0 +1,13 @@
+#include "KeccakPRG.h"
+#include <stdint.h>
+
+typedef KeccakWidth200_SpongePRG_Instance prng_state;
+
+void prng_init(prng_state *state);
+
+void prng_seed(prng_state *state, const uint8_t *seed, size_t size);
+
+void prng_get(prng_state *state, uint8_t *out, size_t size);
+
+
+
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
index ec107b8..12c1936 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
@@ -76,6 +76,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getC
return result;
}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ yarrow_start(&ltc_prng);
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ yarrow_add_entropy(seed_data, seed_length, &ltc_prng);
+ yarrow_ready(&ltc_prng);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported(JNIEnv *env, jobject this, jint keysize){
int key_bytes = (keysize + 7) / 8;
const ltc_ecc_set_type * curve = ltc_ecc_sets;
diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java
index d401e58..1ff9556 100644
--- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java
+++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java
@@ -1,6 +1,5 @@
package cz.crcs.ectester.standalone;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java
new file mode 100644
index 0000000..5c7a21f
--- /dev/null
+++ b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java
@@ -0,0 +1,139 @@
+package cz.crcs.ectester.standalone;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junitpioneer.jupiter.StdIo;
+import org.junitpioneer.jupiter.StdOut;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class DeterministicTests {
+
+ static Stream<String> libs() {
+ return Stream.of("Botan", "BouncyCastle", "Crypto++", "IPPCP", "mbedTLS", "Nettle", "OpenSSL", "SunEC", "tomcrypt");
+ // BoringSSL and libgcrypt cannot be easily tested here, because they initialize their RNG only once per process.
+ // LibreSSL hangs in CI.
+ }
+
+ @SuppressWarnings("JUnitMalformedDeclaration")
+ @ParameterizedTest
+ @MethodSource("libs")
+ @StdIo()
+ public void generate(String libName, StdOut out) {
+ String[] args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName};
+ switch (libName) {
+ case "Botan":
+ args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName};
+ break;
+ case "Crypto++":
+ args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName};
+ break;
+ case "Nettle":
+ args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "secp256r1", libName};
+ break;
+ case "mbedTLS":
+ args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", libName};
+ break;
+ }
+ ECTesterStandalone.main(args);
+ String out1 = out.capturedString();
+ ECTesterStandalone.main(args);
+ String out2 = out.capturedString().substring(out1.length());
+ if (!out1.contains(";"))
+ return;
+ List<String> lines1 = out1.lines().collect(Collectors.toList());
+ List<String> lines2 = out2.lines().collect(Collectors.toList());
+ assertEquals(lines1.size(), lines2.size());
+ for (int i = 0; i < lines1.size(); ++i) {
+ String[] parts1 = lines1.get(i).split(";");
+ String[] parts2 = lines2.get(i).split(";");
+ assertEquals(parts1[2], parts2[2]);
+ assertEquals(parts1[3], parts2[3]);
+ }
+ }
+
+ @SuppressWarnings("JUnitMalformedDeclaration")
+ @ParameterizedTest
+ @MethodSource("libs")
+ @StdIo()
+ public void ecdh(String libName, StdOut out) {
+ String[] args = new String[]{"ecdh", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName};
+ switch (libName) {
+ case "Nettle":
+ args = new String[]{"ecdh", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "secp256r1", libName};
+ break;
+ case "Crypto++":
+ args = new String[]{"ecdh", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName};
+ break;
+ case "mbedTLS":
+ args = new String[]{"ecdh", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", libName};
+ break;
+ }
+ ECTesterStandalone.main(args);
+ String out1 = out.capturedString();
+ ECTesterStandalone.main(args);
+ String out2 = out.capturedString().substring(out1.length());
+ if (!out1.contains(";"))
+ return;
+ List<String> lines1 = out1.lines().collect(Collectors.toList());
+ List<String> lines2 = out2.lines().collect(Collectors.toList());
+ assertEquals(lines1.size(), lines2.size());
+ for (int i = 0; i < lines1.size(); ++i) {
+ String[] parts1 = lines1.get(i).split(";");
+ String[] parts2 = lines2.get(i).split(";");
+ assertEquals(parts1[2], parts2[2]); // pubkey
+ assertEquals(parts1[3], parts2[3]); // privkey
+ assertEquals(parts1[4], parts2[4]); // secret
+ }
+ }
+
+ @SuppressWarnings("JUnitMalformedDeclaration")
+ @ParameterizedTest
+ @MethodSource("libs")
+ @StdIo()
+ public void ecdsa(String libName, StdOut out) {
+ String[] args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", libName};
+ switch (libName) {
+ case "Nettle":
+ args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-cn", "secp256r1", "-t", "NONEwithECDSA", libName};
+ break;
+ case "OpenSSL":
+ case "tomcrypt":
+ args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName};
+ break;
+ case "IPPCP":
+ // TODO: Weird, IPPCP cannot sign less than 4 bytes.
+ args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName};
+ break;
+ case "Crypto++":
+ args = new String[]{"ecdsa", "-ps", "12345678", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDSA", libName};
+ break;
+ case "LibreSSL":
+ case "mbedTLS":
+ args = new String[]{"ecdsa", "-ps", "12345678", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName};
+ break;
+ }
+ ECTesterStandalone.main(args);
+ String out1 = out.capturedString();
+ ECTesterStandalone.main(args);
+ String out2 = out.capturedString().substring(out1.length());
+ if (!out1.contains(";"))
+ return;
+ List<String> lines1 = out1.lines().collect(Collectors.toList());
+ List<String> lines2 = out2.lines().collect(Collectors.toList());
+ assertEquals(lines1.size(), lines2.size());
+ for (int i = 0; i < lines1.size(); ++i) {
+ String[] parts1 = lines1.get(i).split(";");
+ String[] parts2 = lines2.get(i).split(";");
+ assertEquals(parts1[3], parts2[3]); // data
+ assertEquals(parts1[4], parts2[4]); // pubkey
+ assertEquals(parts1[5], parts2[5]); // privkey
+ assertEquals(parts1[6], parts2[6]); // signature
+ assertEquals(parts1[7], parts2[7]); // nonce
+ }
+ }
+}