Skip to content

Commit

Permalink
Add support for deterministic PRNG to OpenSSL.
Browse files Browse the repository at this point in the history
  • Loading branch information
J08nY committed Aug 5, 2024
1 parent 09f3ebf commit 46b290e
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,16 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException {
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).").hasArgs().argName("seed").optionalArg(false).numberOfArgs(1).build();

Options testOpts = new Options();
testOpts.addOption(bits);
testOpts.addOption(namedCurve);
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());
Expand All @@ -215,6 +217,7 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException {
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());
Expand All @@ -231,6 +234,7 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException {
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());
Expand All @@ -246,6 +250,7 @@ private TreeCommandLine parseArgs(String[] args) throws ParseException {
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.");
Expand Down Expand Up @@ -307,6 +312,7 @@ private void listLibraries() {
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(", ")));
Expand Down Expand Up @@ -430,6 +436,12 @@ private void ecdh() throws NoSuchAlgorithmException, InvalidAlgorithmParameterEx
kpg.initialize(spec);
}

if (cli.hasOption("ecdh.prng-seed")) {
String seedString = cli.getOptionValue("ecdh.prng-seed");
byte[] seed = ByteUtil.hexToBytes(seedString, true);
lib.setupDeterministicPRNG(seed);
}

if (cli.hasOption("ecdh.time-source")) {
if (!lib.setNativeTimingType(cli.getOptionValue("ecdh.time-source"))) {
System.err.println("Couldn't set native time source.");
Expand Down Expand Up @@ -586,6 +598,12 @@ private void ecdsa() throws NoSuchAlgorithmException, InvalidAlgorithmParameterE
kpg.initialize(new ECGenParameterSpec(curveName));
}

if (cli.hasOption("ecdsa.prng-seed")) {
String seedString = cli.getOptionValue("ecdsa.prng-seed");
byte[] seed = ByteUtil.hexToBytes(seedString, true);
lib.setupDeterministicPRNG(seed);
}

if (cli.hasOption("ecdsa.time-source")) {
if (!lib.setNativeTimingType(cli.getOptionValue("ecdsa.time-source"))) {
System.err.println("Couldn't set native time source.");
Expand Down Expand Up @@ -722,6 +740,12 @@ private void generate() throws NoSuchAlgorithmException, InvalidAlgorithmParamet
kpg.initialize(new ECGenParameterSpec(curveName));
}

if (cli.hasOption("generate.prng-seed")) {
String seedString = cli.getOptionValue("generate.prng-seed");
byte[] seed = ByteUtil.hexToBytes(seedString, true);
lib.setupDeterministicPRNG(seed);
}

if (cli.hasOption("generate.time-source")) {
if (!lib.setNativeTimingType(cli.getOptionValue("generate.time-source"))) {
System.err.println("Couldn't set native time source.");
Expand Down Expand Up @@ -818,6 +842,13 @@ private void test() throws TestException, ParserConfigurationException, FileNotF
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);
lib.setupDeterministicPRNG(seed);
}

switch (testSuite) {
case "test-vectors":
suite = new StandaloneTestVectorSuite(writer, cfg, cli);
Expand Down Expand Up @@ -997,6 +1028,15 @@ boolean readOptions(TreeCommandLine cli) {
}
}

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;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ public OpensslLib() {

@Override
public native Set<String> getCurves();

@Override
public native boolean supportsDeterministicPRNG();

@Override
public native void setupDeterministicPRNG(byte[] seed);
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,28 @@ public Set<String> getNativeTimingSupport() {
}

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 void setupDeterministicPRNG(byte[] seed) {
}

@Override
public Set<KeyAgreementIdent> getKAs() {
return getIdents("KeyAgreement", KeyAgreementIdent::get);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 46b290e

Please sign in to comment.