From fcc645f2627167c35e63cb7e7595000d65c70a1e Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 3 Apr 2024 12:37:19 +0200 Subject: Fix CI lib build. --- standalone/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standalone/build.gradle.kts b/standalone/build.gradle.kts index 27764eb..f8d7f9b 100644 --- a/standalone/build.gradle.kts +++ b/standalone/build.gradle.kts @@ -90,7 +90,7 @@ tasks.register("libs") { workingDir("src/main/resources/cz/crcs/ectester/standalone/libs/jni") environment("PROJECT_ROOT_PATH", rootDir.absolutePath) - val libName = findProperty("libName") ?: "" + val libName = findProperty("libName") ?: "all" if ( libName == "" ) { println("Building all libraries") } else { -- cgit v1.3.1 From bc4b360520df886088358528d311e7ea46a2bcda Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 25 Apr 2024 15:01:28 +0200 Subject: Add pseudoprime-p curves. --- .../cz/crcs/ectester/data/wrong/curves.xml | 42 ++++++++++++++++++++++ .../cz/crcs/ectester/data/wrong/pseudo192.csv | 1 + .../cz/crcs/ectester/data/wrong/pseudo224.csv | 1 + .../cz/crcs/ectester/data/wrong/pseudo256.csv | 1 + .../cz/crcs/ectester/data/wrong/pseudo384.csv | 1 + .../cz/crcs/ectester/data/wrong/pseudo512.csv | 1 + .../cz/crcs/ectester/data/wrong/pseudo521.csv | 1 + 7 files changed, 48 insertions(+) create mode 100644 common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo192.csv create mode 100644 common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo224.csv create mode 100644 common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo256.csv create mode 100644 common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo384.csv create mode 100644 common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo512.csv create mode 100644 common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo521.csv diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/curves.xml b/common/src/main/resources/cz/crcs/ectester/data/wrong/curves.xml index 2a51474..9087940 100644 --- a/common/src/main/resources/cz/crcs/ectester/data/wrong/curves.xml +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/curves.xml @@ -92,4 +92,46 @@ wrongt571.csv The field polynomial is not irreducible in F_2^571[x]. + + pseudo192 + 192 + prime + pseudo192.csv + The field is not prime (but a Carmichael pseudoprime, see https://github.com/crocs-muni/fooling-primality-tests/). + + + pseudo224 + 224 + prime + pseudo224.csv + The field is not prime (but a Carmichael pseudoprime, see https://github.com/crocs-muni/fooling-primality-tests/). + + + pseudo256 + 256 + prime + pseudo256.csv + The field is not prime (but a Carmichael pseudoprime, see https://github.com/crocs-muni/fooling-primality-tests/). + + + pseudo384 + 384 + prime + pseudo384.csv + The field is not prime (but a Carmichael pseudoprime, see https://github.com/crocs-muni/fooling-primality-tests/). + + + pseudo512 + 512 + prime + pseudo512.csv + The field is not prime (but a Carmichael pseudoprime, see https://github.com/crocs-muni/fooling-primality-tests/). + + + pseudo521 + 521 + prime + pseudo521.csv + The field is not prime (but a Carmichael pseudoprime, see https://github.com/crocs-muni/fooling-primality-tests/). + \ No newline at end of file diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo192.csv b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo192.csv new file mode 100644 index 0000000..c98e63b --- /dev/null +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo192.csv @@ -0,0 +1 @@ +0xf7601c102e5605a4510b865b28287060ae6002956371b4f7,0x429c8107ce7063a45234aeadd30c021acc6bdaff6531af7d,0x9637284c287bc5c97c574dc8f91d03e5f58f516bfdb77601,0x1f7fe14d44df79fcfbd9225173d39784374bc08a80a8dc40,0xdb2ff34213f3214f1aa4e273e48efaf8362292f4e0ed0b9f,0xf7601c102487dad5b1e6fbcb61193546c31f16a71903f85d,0x0001 \ No newline at end of file diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo224.csv b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo224.csv new file mode 100644 index 0000000..cf781d6 --- /dev/null +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo224.csv @@ -0,0 +1 @@ +0xf54255f919b6fec4c9c9788c0dc432b8a50b7331e836a4fff9c5bc7f,0x270b8817bc48b1d56401abf8964e6fc785771d2a26130f8a572682f1,0xe28250a72ac83dd064b08cb83e8d2b678330d4dfd5193179088cb5cb,0xd0a2d469eda6a9c5bf9568459a02e2e65901f907f766891ad2a323cd,0x580e1fbfb94793f5880e36d6a2229c2fb082db0f3270f0b3ec4ce2a8,0xf54255f9581e15675cedd50065fa01410df6bfb6e17a2c69747246e5,0x0001 \ No newline at end of file diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo256.csv b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo256.csv new file mode 100644 index 0000000..ef14dc4 --- /dev/null +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo256.csv @@ -0,0 +1 @@ +0x89ae5b1ffa52bd5a6e1e9627d2fef2b1658f5ae93ce0dabecead0f8cf294909b,0x35fe79c1bdac3f16080f6f763f1947c97fe841510d807e632fdb0abca45b539d,0x1da2a1152d54cc6d19da48bfbd8c31f6d7aba41fdbb744ef60c3ffb0a1b1b3cb,0x6ef9419070b90eaec6914e8c4809c3fe1c868b9857874abc4929321a021ef679,0x2391630ddc525199e2f65883d35623545cccd58496caa8b2e3fb8a84df6996e6,0x89ae5b1ffad4189f719eb3801d3a65986202d48cbab151d32b992e92dd589161,0x0001 \ No newline at end of file diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo384.csv b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo384.csv new file mode 100644 index 0000000..ac1f589 --- /dev/null +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo384.csv @@ -0,0 +1 @@ +0xbddc881aa619fc8a2f4dedb315f0b55c8c0cca4d7aac4e595c96504eb2e8860489bd824340028f49ca90272998729fe7,0x1595f6abcbb9bea724adb7df2129472f9f4d7ed83e2c9e7a52dc8cd12ef36b7a209f46afa553901d7ecf0d98618dabcf,0xb6bf3f61901462bf181b096d61aa7ee00310d110f739cbf95fccf7faa7f529052ee8758210a9d6c10de2790e4ab7f1e3,0x6525e4141411e472233e794116f285835ed743c77d21cac612c9b8a5000fa58407754ff242671f4ca8478b6bece46ad9,0x335f77556d279a9fd8701c26f14a13646b927d3ab86c165fafb5e3ee08f3797b819eb0eea2e6e3a569c63271c406d3bb,0xbddc881aa619fc85d46958aae14456922f956e5a8bf1d5f3f889d9d14ff5ae4ef373c260215503b442e5a6f88e1b609d,0x0001 \ No newline at end of file diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo512.csv b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo512.csv new file mode 100644 index 0000000..3562558 --- /dev/null +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo512.csv @@ -0,0 +1 @@ +0xd7489dfb959fd93de1b90bcdd949ea38d11c7e3637ab48f56fb1b2b34e6593fe3cf189e9c2f3166ddefc270747002d1914c558a23dceab08875e75a6b3b3c88f,0x15ae03d8fdf64becd183b64e8a235322be8342124a3e88ae8691ac7e635f424afad39da56169deb4ee25bfb4538054f6208f1bcb7abff14d6ea61ae9f8d2349b,0x7d22f3ece4a500edd384cae7de2f60377a6852e6d3a417374a881b0d83b8f747fba5106a011c76b2176916cd5fa68371c0ba0b2786b1dcdac80ad329b1a83f28,0x0aead0caddeda9ee70fe1976af1a96a410f96fbe65273a986bc88e3e7f3bd6e24d1dc728a04fecfd17e9ddfdfe9472359d39f877761dcdc73a0ee6514ba4894b,0x03f830aef9bfd770119e28a8de3f94119517508839df651129e8a6819c4e86df580179f97821d266d0e205f7536ab49cc04298aa88dde463d638689645188d86,0xd7489dfb959fd93de1b8fe30119d6f138fbeef529543d12c03f91d34c545a75197f79a0083650dbebee8fa12d39f2902101eed3f2e1963470d77dfe2204a02c7,0x0001 \ No newline at end of file diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo521.csv b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo521.csv new file mode 100644 index 0000000..4e7c30e --- /dev/null +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/pseudo521.csv @@ -0,0 +1 @@ +0x153212291c26fe063b78bbca97d35dda6b0b349fe3fc1d4dee21786fc85296e22d93ce855a2d3ed048498c6a1f378cea240f029df302cffb658efe9e12379629acb,0x5a4b83e21db14397282aab529b230058a165962eadf8e8f15703ca5b91501463fc8bf866d7f1a2ce785c4ff0c5797e20e3fb6952bd42e3421ed1c589b2853a0c30,0x1196a7bc6d754b0224fcace252f9056acebba295a7a0763a95fd0fa90cca4bbcc1d030cbee049d06e103bb28c8b870a1d5989d9c56870ff7fde969f3bfd0278fbf7,0xd74e5bf4d166a2d75d57d49be58f9bf3900bda81bbb283a8f311d9972c7cd1ed547403b52c657af133297f852f938b6a7ba8ef52c2ca8eb79799b15f7123c5d2af,0x7ed2303056596fb09cfade2ca0f691c515da266565ba5afa4700c6c6ed38091f3cf4fdc67ee1426b849bb9be26c1e8c3b53530fc4510dad8b7badc81bad7276c5b,0x153212291c26fe063b78bc114fd2c18a365faa9b5b3fecbb87c2690125099ddd8baa5052aa2fda7f14120d3d6af0ac185902f97bae06a009588286cf5ce93b1cce3,0x0001 \ No newline at end of file -- cgit v1.3.1 From ee5c50d8b2491da2966f4b0730013765ab2507bc Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 25 Apr 2024 15:47:49 +0200 Subject: Add some output to tests as they run. --- .../ectester/common/output/BaseTextTestWriter.java | 17 +++++++++++++++ .../ectester/common/output/BaseXMLTestWriter.java | 10 +++++++++ .../ectester/common/output/BaseYAMLTestWriter.java | 10 +++++++++ .../crcs/ectester/common/output/TeeTestWriter.java | 14 +++++++++++++ .../cz/crcs/ectester/common/output/TestWriter.java | 24 ++++++++++++++++------ .../cz/crcs/ectester/common/test/TestSuite.java | 2 ++ 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java index 5c449db..4670f95 100644 --- a/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java +++ b/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java @@ -113,6 +113,23 @@ public abstract class BaseTextTestWriter implements TestWriter { return line + out.toString(); } + @Override + public void beginTest(Test t) { + if (t instanceof CompoundTest) { + CompoundTest test = (CompoundTest) t; + } else { + SimpleTest test = (SimpleTest) t; + } + output.print("Running ▶ " + t.getDescription()); + output.flush(); + } + + + @Override + public void endTest(Test t) { + output.print("\33[2K\r"); + } + @Override public void outputTest(Test t, int index) { if (!t.hasRun()) diff --git a/common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java index 53970dd..5157ef0 100644 --- a/common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java +++ b/common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java @@ -115,6 +115,16 @@ public abstract class BaseXMLTestWriter implements TestWriter { return testElem; } + @Override + public void beginTest(Test t) { + + } + + @Override + public void endTest(Test t) { + + } + @Override public void outputTest(Test t, int index) { if (!t.hasRun()) diff --git a/common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java index e054563..c3a42ea 100644 --- a/common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java +++ b/common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java @@ -91,6 +91,16 @@ public abstract class BaseYAMLTestWriter implements TestWriter { return testObj; } + @Override + public void beginTest(Test t) { + + } + + @Override + public void endTest(Test t) { + + } + @Override public void outputTest(Test t, int index) { if (!t.hasRun()) diff --git a/common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java index 58a0a15..7635644 100644 --- a/common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java +++ b/common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java @@ -20,6 +20,20 @@ public class TeeTestWriter implements TestWriter { } } + @Override + public void beginTest(Test t) { + for (TestWriter writer : writers) { + writer.beginTest(t); + } + } + + @Override + public void endTest(Test t) { + for (TestWriter writer : writers) { + writer.endTest(t); + } + } + @Override public void outputTest(Test t, int index) { for (TestWriter writer : writers) { diff --git a/common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java index 67aeccb..7368c0a 100644 --- a/common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java +++ b/common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java @@ -19,20 +19,32 @@ public interface TestWriter { void begin(TestSuite suite); /** - * @param t - * @param index + * Begin the test (before it is run). + * @param t Test to begin output of. + */ + void beginTest(Test t); + + /** + * End the test (after it is run, or errored out). + * @param t Test to end output of. + */ + void endTest(Test t); + + /** + * @param t Test to output. + * @param index Index of the test. */ void outputTest(Test t, int index); /** - * @param t - * @param cause - * @param index + * @param t Test to output the error from. + * @param cause Throwable to output. + * @param index Index of the test. */ void outputError(Test t, Throwable cause, int index); /** - * + * End writing the TestSuite. */ void end(); } diff --git a/common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java b/common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java index b12680a..091b008 100644 --- a/common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java +++ b/common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java @@ -55,7 +55,9 @@ public abstract class TestSuite { */ protected T runTest(T t) { running = t; + writer.beginTest(t); t.run(); + writer.endTest(t); running = null; return t; } -- cgit v1.3.1 From 1ec0cd462865f06c673e54ed4556079d3a0917a6 Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 25 Apr 2024 17:08:37 +0200 Subject: Add XDH and EdDSA keygen. --- .github/workflows/build.yml | 2 +- .../ectester/standalone/ECTesterStandalone.java | 58 ++++++++++++++++++---- .../standalone/consts/KeyPairGeneratorIdent.java | 9 ++++ 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ab2a2ee..8ad7bcd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -88,7 +88,7 @@ jobs: strategy: matrix: - java: [ "11", "17", "21" ] + java: [ "17", "21" ] env: # ffs: https://github.com/adoptium/adoptium-support/issues/485 !!! # also, add the wolfcrypt JNI path 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 c702dee..bf9a9ef 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -37,11 +37,14 @@ import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; import cz.crcs.ectester.standalone.consts.SignatureIdent; import cz.crcs.ectester.standalone.libs.*; import cz.crcs.ectester.standalone.output.FileTestWriter; -import cz.crcs.ectester.standalone.output.TextTestWriter; -import cz.crcs.ectester.standalone.output.XMLTestWriter; -import cz.crcs.ectester.standalone.output.YAMLTestWriter; import cz.crcs.ectester.standalone.test.suites.*; import org.apache.commons.cli.*; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.jcajce.interfaces.EdDSAPrivateKey; +import org.bouncycastle.jcajce.interfaces.EdDSAPublicKey; +import org.bouncycastle.jcajce.interfaces.XDHPrivateKey; +import org.bouncycastle.jcajce.interfaces.XDHPublicKey; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; @@ -55,8 +58,7 @@ import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.security.*; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; +import java.security.interfaces.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; @@ -158,6 +160,8 @@ public class ECTesterStandalone { listIdents(); } else if (cli.isNext("ecdh")) { ecdh(); + } else if (cli.isNext("xdh")) { + xdh(); } else if (cli.isNext("ecdsa")) { ecdsa(); } else if (cli.isNext("generate")) { @@ -232,6 +236,11 @@ public class ECTesterStandalone { ParserOptions ecdh = new ParserOptions(new DefaultParser(), ecdhOpts, "Perform EC based KeyAgreement."); actions.put("ecdh", ecdh); + Options xdhOpts = new Options(); + xdhOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do XDH [amount] times.").build()); + ParserOptions xdh = new ParserOptions(new DefaultParser(), xdhOpts, "Perform XDH (x25519/x448)."); + actions.put("xdh", xdh); + Options ecdsaOpts = new Options(); ecdsaOpts.addOption(bits); ecdsaOpts.addOption(namedCurve); @@ -512,6 +521,10 @@ public class ECTesterStandalone { } } + private void xdh() { + + } + /** * */ @@ -744,11 +757,36 @@ public class ECTesterStandalone { if (!lib.getNativeTimingSupport().isEmpty()) { elapsed = lib.getLastNativeTiming(); } - ECPublicKey publicKey = (ECPublicKey) kp.getPublic(); - ECPrivateKey privateKey = (ECPrivateKey) kp.getPrivate(); - - String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(publicKey.getW(), publicKey.getParams()), false); - String priv = ByteUtil.bytesToHex(privateKey.getS().toByteArray(), false); + PublicKey pubkey = kp.getPublic(); + PrivateKey privkey = kp.getPrivate(); + String pub; + String priv; + if (pubkey instanceof ECPublicKey && privkey instanceof ECPrivateKey) { + ECPublicKey publicKey = (ECPublicKey) pubkey; + ECPrivateKey privateKey = (ECPrivateKey) privkey; + pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(publicKey.getW(), publicKey.getParams()), false); + priv = ByteUtil.bytesToHex(privateKey.getS().toByteArray(), false); + } else if (pubkey instanceof XECPublicKey && privkey instanceof XECPrivateKey) { + pub = ByteUtil.bytesToHex(((XECPublicKey) pubkey).getU().toByteArray(), false); + priv = ByteUtil.bytesToHex(((XECPrivateKey) privkey).getScalar().get(), false); + } else if (pubkey instanceof EdECPublicKey && privkey instanceof EdECPrivateKey) { + pub = ByteUtil.bytesToHex(((EdECPublicKey) pubkey).getPoint().getY().toByteArray(), false); + priv = ByteUtil.bytesToHex(((EdECPrivateKey) privkey).getBytes().get(), false); + } else if (pubkey instanceof XDHPublicKey && privkey instanceof XDHPrivateKey) { + // Special-case BouncyCastle XDH + pub = ByteUtil.bytesToHex(((XDHPublicKey) pubkey).getU().toByteArray(), false); + PrivateKeyInfo pkinfo = PrivateKeyInfo.getInstance(privkey.getEncoded()); + priv = ByteUtil.bytesToHex(ASN1OctetString.getInstance(pkinfo.getPrivateKey().getOctets()).getOctets(), false); + } else if (pubkey instanceof EdDSAPublicKey && privkey instanceof EdDSAPrivateKey) { + // Special-case BouncyCastle EdDSA + pub = ByteUtil.bytesToHex(((EdDSAPublicKey) pubkey).getPointEncoding(), false); + PrivateKeyInfo pkinfo = PrivateKeyInfo.getInstance(privkey.getEncoded()); + priv = ByteUtil.bytesToHex(ASN1OctetString.getInstance(pkinfo.getPrivateKey().getOctets()).getOctets(), false); + } else { + System.err.println(pubkey.getClass().getCanonicalName()); + System.err.println(privkey.getClass().getCanonicalName()); + break; + } out.printf("%d;%d;%s;%s%n", i, elapsed, pub, priv); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java b/standalone/src/main/java/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java index 83eef75..49b982b 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java @@ -11,6 +11,7 @@ public class KeyPairGeneratorIdent extends Ident { private static final List ALL = new LinkedList<>(); static { + // Short-Weierstrass ALL.add(new KeyPairGeneratorIdent("EC")); ALL.add(new KeyPairGeneratorIdent("ECDH")); ALL.add(new KeyPairGeneratorIdent("ECDSA")); @@ -22,6 +23,14 @@ public class KeyPairGeneratorIdent extends Ident { ALL.add(new KeyPairGeneratorIdent("ECKCDSA")); // ECGDSA? Botan provides. ALL.add(new KeyPairGeneratorIdent("ECGDSA")); + // Montgomery + ALL.add(new KeyPairGeneratorIdent("XDH")); + ALL.add(new KeyPairGeneratorIdent("X25519")); + ALL.add(new KeyPairGeneratorIdent("X448")); + // Twisted-Edwards + ALL.add(new KeyPairGeneratorIdent("EdDSA")); + ALL.add(new KeyPairGeneratorIdent("Ed25519")); + ALL.add(new KeyPairGeneratorIdent("Ed448")); } public static KeyPairGeneratorIdent get(String ident) { -- cgit v1.3.1 From 05bb80b365928e232416b2b0d4a7a915a00078e9 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 26 Apr 2024 23:35:53 +0200 Subject: Sort lists of items in standalone CLI. --- .../main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 bf9a9ef..c5693e8 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -315,19 +315,19 @@ public class ECTesterStandalone { System.out.println(Colors.bold("\t\t- Supports native timing: ") + lib.getNativeTimingSupport().toString()); Set kpgs = lib.getKPGs(); if (!kpgs.isEmpty()) { - System.out.println(Colors.bold("\t\t- KeyPairGenerators: ") + kpgs.stream().map(KeyPairGeneratorIdent::getName).collect(Collectors.joining(", "))); + System.out.println(Colors.bold("\t\t- KeyPairGenerators: ") + kpgs.stream().map(KeyPairGeneratorIdent::getName).sorted().collect(Collectors.joining(", "))); } Set eckas = lib.getKAs(); if (!eckas.isEmpty()) { - System.out.println(Colors.bold("\t\t- KeyAgreements: ") + eckas.stream().map(KeyAgreementIdent::getName).collect(Collectors.joining(", "))); + System.out.println(Colors.bold("\t\t- KeyAgreements: ") + eckas.stream().map(KeyAgreementIdent::getName).sorted().collect(Collectors.joining(", "))); } Set sigs = lib.getSigs(); if (!sigs.isEmpty()) { - System.out.println(Colors.bold("\t\t- Signatures: ") + sigs.stream().map(SignatureIdent::getName).collect(Collectors.joining(", "))); + System.out.println(Colors.bold("\t\t- Signatures: ") + sigs.stream().map(SignatureIdent::getName).sorted().collect(Collectors.joining(", "))); } Set curves = lib.getCurves(); if (!curves.isEmpty()) { - System.out.println(Colors.bold("\t\t- Curves: ") + String.join(", ", curves)); + System.out.println(Colors.bold("\t\t- Curves: ") + curves.stream().sorted().collect(Collectors.joining(", "))); } System.out.println(); } -- cgit v1.3.1 From 8f9179da726be18ab883ac716296dbe2c411d805 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 26 Apr 2024 23:36:06 +0200 Subject: Add XDH and EdDSA idents --- .../crcs/ectester/standalone/consts/KeyAgreementIdent.java | 12 +++++++++++- .../cz/crcs/ectester/standalone/consts/SignatureIdent.java | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java b/standalone/src/main/java/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java index 60c60e8..c0cf793 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java @@ -18,10 +18,11 @@ public class KeyAgreementIdent extends Ident { private static final List ALL = new LinkedList<>(); static { - //https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html + // https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html // Basic ECDH and ECDHC (plain/raw) ALL.add(new KeyAgreementIdent("ECDH")); ALL.add(new KeyAgreementIdent("ECDHC", "ECCDH")); + // ECDH and ECDHC with SHA as KDF, OIDs from RFC 3278 ALL.add(new KeyAgreementIdent("ECDHwithSHA1KDF", true, "1.3.133.16.840.63.0.2")); ALL.add(new KeyAgreementIdent("ECCDHwithSHA1KDF", true, "1.3.133.16.840.63.0.3")); @@ -33,11 +34,13 @@ public class KeyAgreementIdent extends Ident { ALL.add(new KeyAgreementIdent("ECCDHwithSHA384KDF", true, "1.3.132.1.14.2")); ALL.add(new KeyAgreementIdent("ECDHwithSHA512KDF", true, "1.3.132.1.11.3")); ALL.add(new KeyAgreementIdent("ECCDHwithSHA512KDF", true, "1.3.132.1.14.3")); + // Microsoft specific KDF ALL.add(new KeyAgreementIdent("ECDHwithSHA1KDF(CNG)")); ALL.add(new KeyAgreementIdent("ECDHwithSHA256KDF(CNG)")); ALL.add(new KeyAgreementIdent("ECDHwithSHA384KDF(CNG)")); ALL.add(new KeyAgreementIdent("ECDHwithSHA512KDF(CNG)")); + // CKDF requires custom AlgorithmParameterSpec (only BouncyCastle) //ALL.add(new KeyAgreementIdent("ECDHwithSHA1CKDF", true)); //ALL.add(new KeyAgreementIdent("ECCDHwithSHA1CKDF", true)); @@ -47,6 +50,7 @@ public class KeyAgreementIdent extends Ident { //ALL.add(new KeyAgreementIdent("ECCDHwithSHA384CKDF", true)); //ALL.add(new KeyAgreementIdent("ECDHwithSHA512CKDF", true)); //ALL.add(new KeyAgreementIdent("ECCDHwithSHA512CKDF", true)); + // ECMQV - Disable for now as it needs diferent params(too different from DH) //ALL.add(new KeyAgreementIdent("ECMQV")); //ALL.add(new KeyAgreementIdent("ECMQVwithSHA1KDF", true)); @@ -59,10 +63,16 @@ public class KeyAgreementIdent extends Ident { //ALL.add(new KeyAgreementIdent("ECMQVwithSHA256CKDF", true, "1.3.132.1.15.1")); //ALL.add(new KeyAgreementIdent("ECMQVwithSHA384CKDF", true, "1.3.132.1.15.2")); //ALL.add(new KeyAgreementIdent("ECMQVwithSHA512CKDF", true, "1.3.132.1.15.3")); + // ECVKO - Disable for now as it needs diferent params(too different from DH) //ALL.add(new KeyAgreementIdent("ECVKO", "ECGOST3410", "1.2.643.2.2.19", "GOST-3410-2001", "1.2.643.2.2.96")); //ALL.add(new KeyAgreementIdent("ECVKO256", "ECGOST3410-2012-256", "1.2.643.7.1.1.6.1", "1.2.643.7.1.1.1.1")); //ALL.add(new KeyAgreementIdent("ECVKO512", "ECGOST3410-2012-512", "1.2.643.7.1.1.6.2", "1.2.643.7.1.1.1.2")); + + // XDH (RFC 7748) + ALL.add(new KeyAgreementIdent("XDH")); + ALL.add(new KeyAgreementIdent("X25519")); + ALL.add(new KeyAgreementIdent("X448")); } public static KeyAgreementIdent get(String ident) { diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/consts/SignatureIdent.java b/standalone/src/main/java/cz/crcs/ectester/standalone/consts/SignatureIdent.java index c3913b7..a65d0c5 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/consts/SignatureIdent.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/consts/SignatureIdent.java @@ -30,17 +30,20 @@ public class SignatureIdent extends Ident { ALL.add(new SignatureIdent("SHA3-384withECDSA", "SHA3-384/ECDSA", "2.16.840.1.101.3.4.3.11")); ALL.add(new SignatureIdent("SHA3-512withECDSA", "SHA3-512/ECDSA", "2.16.840.1.101.3.4.3.12")); ALL.add(new SignatureIdent("RIPEMD160withECDSA", "RIPEMD160/ECDSA", "1.3.36.3.3.2.2")); + // ECNR ALL.add(new SignatureIdent("SHA1withECNR")); ALL.add(new SignatureIdent("SHA224withECNR")); ALL.add(new SignatureIdent("SHA256withECNR")); ALL.add(new SignatureIdent("SHA512withECNR")); + // CVC-ECDSA ALL.add(new SignatureIdent("SHA1withCVC-ECDSA", "SHA1/CVC-ECDSA", "0.4.0.127.0.7.2.2.2.2.1")); ALL.add(new SignatureIdent("SHA224withCVC-ECDSA", "SHA224/CVC-ECDSA", "0.4.0.127.0.7.2.2.2.2.2")); ALL.add(new SignatureIdent("SHA256withCVC-ECDSA", "SHA256/CVC-ECDSA", "0.4.0.127.0.7.2.2.2.2.3")); ALL.add(new SignatureIdent("SHA384withCVC-ECDSA", "SHA384/CVC-ECDSA", "0.4.0.127.0.7.2.2.2.2.4")); ALL.add(new SignatureIdent("SHA512withCVC-ECDSA", "SHA512/CVC-ECDSA", "0.4.0.127.0.7.2.2.2.2.5")); + // PLAIN-ECDSA ALL.add(new SignatureIdent("SHA1withPLAIN-ECDSA", "SHA1/PLAIN-ECDSA", "0.4.0.127.0.7.1.1.4.1.1")); ALL.add(new SignatureIdent("SHA224withPLAIN-ECDSA", "SHA224/PLAIN-ECDSA", "0.4.0.127.0.7.1.1.4.1.2")); @@ -48,6 +51,7 @@ public class SignatureIdent extends Ident { ALL.add(new SignatureIdent("SHA384withPLAIN-ECDSA", "SHA384/PLAIN-ECDSA", "0.4.0.127.0.7.1.1.4.1.4")); ALL.add(new SignatureIdent("SHA512withPLAIN-ECDSA", "SHA512/PLAIN-ECDSA", "0.4.0.127.0.7.1.1.4.1.5")); ALL.add(new SignatureIdent("RIPEMD160withPLAIN-ECDSA", "RIPEMD160/PLAIN-ECDSA", "0.4.0.127.0.7.1.1.4.1.6")); + // ECGOST ALL.add(new SignatureIdent("ECGOST3410", "ECGOST-3410", "GOST-3410-2001")); ALL.add(new SignatureIdent("GOST3411withECGOST3410", "GOST3411/ECGOST3410", "1.2.643.2.2.3")); @@ -56,6 +60,7 @@ public class SignatureIdent extends Ident { ALL.add(new SignatureIdent("ECGOST3410-2012-512", "GOST-3410-2012-512")); ALL.add(new SignatureIdent("GOST3411-2012-512withECGOST3410-2012-512", "GOST3411-2012-512/ECGOST3410-2012-5120", "1.2.643.7.1.1.3.3")); ALL.add(new SignatureIdent("SM3withSM2")); + // ECDDSA (rfc6979?) ALL.add(new SignatureIdent("ECDDSA", "SHA1withECDDSA", "SHA1withDETECDSA", "DETECDSA", "ECDETDSA")); ALL.add(new SignatureIdent("SHA224withECDDSA", "SHA224withDETECDSA")); @@ -66,6 +71,7 @@ public class SignatureIdent extends Ident { ALL.add(new SignatureIdent("SHA3-256withECDDSA", "SHA3-256withDETECDSA")); ALL.add(new SignatureIdent("SHA3-384withECDDSA", "SHA3-384withDETECDSA")); ALL.add(new SignatureIdent("SHA3-512withECDDSA", "SHA3-512withDETECDSA")); + // ECKCDSA? Botan provides. ALL.add(new SignatureIdent("ECKCDSA", "SHA1withECKCDSA", "1.2.410.200004.1.100.4.3")); ALL.add(new SignatureIdent("NONEwithECKCDSA")); @@ -74,6 +80,7 @@ public class SignatureIdent extends Ident { ALL.add(new SignatureIdent("SHA256withECKCDSA", "1.2.410.200004.1.100.4.5")); ALL.add(new SignatureIdent("SHA384withECKCDSA")); ALL.add(new SignatureIdent("SHA512withECKCDSA")); + // ECGDSA? Botan provides. ALL.add(new SignatureIdent("ECGDSA", "SHA1withECGDSA", "1.3.36.3.3.2.5.4.2")); ALL.add(new SignatureIdent("NONEwithECGDSA")); @@ -82,6 +89,11 @@ public class SignatureIdent extends Ident { ALL.add(new SignatureIdent("SHA224withECGDSA", "1.3.36.3.3.2.5.4.4")); ALL.add(new SignatureIdent("SHA384withECGDSA", "1.3.36.3.3.2.5.4.5")); ALL.add(new SignatureIdent("SHA512withECGDSA", "1.3.36.3.3.2.5.4.6")); + + // EdDSA (RFC 8032) + ALL.add(new SignatureIdent("EdDSA")); + ALL.add(new SignatureIdent("Ed25519")); + ALL.add(new SignatureIdent("Ed448")); } public static SignatureIdent get(String ident) { -- cgit v1.3.1 From 6a9f2181e9fa0fad8732261bb923b0c24b232747 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 27 Apr 2024 00:06:25 +0200 Subject: Add XDH to standalone CLI. --- .../java/cz/crcs/ectester/common/util/ECUtil.java | 54 ++++++++++++++++++--- .../ectester/standalone/ECTesterStandalone.java | 56 +++++----------------- 2 files changed, 61 insertions(+), 49 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java index f9be536..74fccc9 100644 --- a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java +++ b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java @@ -2,20 +2,22 @@ package cz.crcs.ectester.common.util; import cz.crcs.ectester.common.ec.*; import cz.crcs.ectester.data.EC_Store; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.signers.PlainDSAEncoding; import org.bouncycastle.crypto.signers.StandardDSAEncoding; +import org.bouncycastle.jcajce.interfaces.EdDSAPrivateKey; +import org.bouncycastle.jcajce.interfaces.EdDSAPublicKey; +import org.bouncycastle.jcajce.interfaces.XDHPrivateKey; +import org.bouncycastle.jcajce.interfaces.XDHPublicKey; import java.io.FileInputStream; import java.io.IOException; import java.math.BigInteger; import java.nio.charset.StandardCharsets; -import java.security.KeyPair; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.interfaces.ECKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; +import java.security.*; +import java.security.interfaces.*; import java.security.spec.*; import java.util.LinkedList; import java.util.List; @@ -456,6 +458,46 @@ public class ECUtil { return null; } + public static byte[] pubkeyToBytes(PublicKey pubkey) { + if (pubkey instanceof ECPublicKey) { + ECPublicKey ecPublicKey = (ECPublicKey) pubkey; + return ECUtil.toX962Uncompressed(ecPublicKey.getW(), ecPublicKey.getParams()); + } else if (pubkey instanceof XECPublicKey) { + XECPublicKey xedPublicKey = (XECPublicKey) pubkey; + return xedPublicKey.getU().toByteArray(); + } else if (pubkey instanceof EdECPublicKey) { + EdECPublicKey edECPublicKey = (EdECPublicKey) pubkey; + return edECPublicKey.getPoint().getY().toByteArray(); + } else if (pubkey instanceof XDHPublicKey) { + XDHPublicKey xdhPublicKey = (XDHPublicKey) pubkey; + return xdhPublicKey.getU().toByteArray(); + // Special-case BouncyCastle XDH + } else if (pubkey instanceof EdDSAPublicKey) { + EdDSAPublicKey edDSAPublicKey = (EdDSAPublicKey) pubkey; + // Special-case BouncyCastle EdDSA + return edDSAPublicKey.getPointEncoding(); + } + return null; + } + + public static byte[] privkeyToBytes(PrivateKey privkey) { + if (privkey instanceof ECPrivateKey) { + ECPrivateKey ecPrivateKey = (ECPrivateKey) privkey; + return ecPrivateKey.getS().toByteArray(); + } else if (privkey instanceof XECPrivateKey) { + XECPrivateKey xecPrivateKey = (XECPrivateKey) privkey; + return xecPrivateKey.getScalar().get(); + } else if (privkey instanceof EdECPrivateKey) { + EdECPrivateKey edECPrivateKey = (EdECPrivateKey) privkey; + return edECPrivateKey.getBytes().get(); + } else if (privkey instanceof XDHPrivateKey || privkey instanceof EdDSAPrivateKey) { + // Special-case BouncyCastle XDH and EdDSA + PrivateKeyInfo xpkinfo = PrivateKeyInfo.getInstance(privkey.getEncoded()); + return ASN1OctetString.getInstance(xpkinfo.getPrivateKey().getOctets()).getOctets(); + } + return null; + } + public static boolean equalKeyPairParameters(ECPrivateKey priv, ECPublicKey pub) { if (priv == null || pub == null) { return false; 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 c5693e8..2dc5040 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -62,6 +62,7 @@ import java.security.interfaces.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; +import java.security.spec.NamedParameterSpec; import java.util.*; import java.util.stream.Collectors; @@ -160,8 +161,6 @@ public class ECTesterStandalone { listIdents(); } else if (cli.isNext("ecdh")) { ecdh(); - } else if (cli.isNext("xdh")) { - xdh(); } else if (cli.isNext("ecdsa")) { ecdsa(); } else if (cli.isNext("generate")) { @@ -236,11 +235,6 @@ public class ECTesterStandalone { ParserOptions ecdh = new ParserOptions(new DefaultParser(), ecdhOpts, "Perform EC based KeyAgreement."); actions.put("ecdh", ecdh); - Options xdhOpts = new Options(); - xdhOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do XDH [amount] times.").build()); - ParserOptions xdh = new ParserOptions(new DefaultParser(), xdhOpts, "Perform XDH (x25519/x448)."); - actions.put("xdh", xdh); - Options ecdsaOpts = new Options(); ecdsaOpts.addOption(bits); ecdsaOpts.addOption(namedCurve); @@ -467,8 +461,8 @@ public class ECTesterStandalone { other = kpg.genKeyPair(); } - ECPrivateKey privkey = (ECPrivateKey) ECUtil.loadKey(EC_Consts.PARAMETER_S, cli.getOptionValue("ecdh.named-private"), cli.getOptionValue("ecdh.private"), spec); - ECPublicKey pubkey = (ECPublicKey) ECUtil.loadKey(EC_Consts.PARAMETER_W, cli.getOptionValue("ecdh.named-public"), cli.getOptionValue("ecdh.public"), spec); + PrivateKey privkey = (ECPrivateKey) ECUtil.loadKey(EC_Consts.PARAMETER_S, cli.getOptionValue("ecdh.named-private"), cli.getOptionValue("ecdh.private"), spec); + PublicKey pubkey = (ECPublicKey) ECUtil.loadKey(EC_Consts.PARAMETER_W, cli.getOptionValue("ecdh.named-public"), cli.getOptionValue("ecdh.public"), spec); int amount = Integer.parseInt(cli.getOptionValue("ecdh.amount", "1")); for (int i = 0; i < amount || amount == 0; ++i) { @@ -480,11 +474,11 @@ public class ECTesterStandalone { } if (!cli.hasOption("ecdh.named-private") && !cli.hasOption("ecdh.private")) { - privkey = (ECPrivateKey) one.getPrivate(); + privkey = one.getPrivate(); } if (!cli.hasOption("ecdh.named-public") && !cli.hasOption("ecdh.public")) { - pubkey = (ECPublicKey) other.getPublic(); + pubkey = other.getPublic(); } long elapsed = -System.nanoTime(); @@ -510,8 +504,8 @@ public class ECTesterStandalone { } ka = kaIdent.getInstance(lib.getProvider()); - String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false); - String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false); + String pub = ByteUtil.bytesToHex(ECUtil.pubkeyToBytes(pubkey), false); + String priv = ByteUtil.bytesToHex(ECUtil.privkeyToBytes(privkey), false); String dh = ByteUtil.bytesToHex(result, false); out.printf("%d;%d;%s;%s;%s%n", i, elapsed, pub, priv, dh); } @@ -521,10 +515,6 @@ public class ECTesterStandalone { } } - private void xdh() { - - } - /** * */ @@ -759,30 +749,11 @@ public class ECTesterStandalone { } PublicKey pubkey = kp.getPublic(); PrivateKey privkey = kp.getPrivate(); - String pub; - String priv; - if (pubkey instanceof ECPublicKey && privkey instanceof ECPrivateKey) { - ECPublicKey publicKey = (ECPublicKey) pubkey; - ECPrivateKey privateKey = (ECPrivateKey) privkey; - pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(publicKey.getW(), publicKey.getParams()), false); - priv = ByteUtil.bytesToHex(privateKey.getS().toByteArray(), false); - } else if (pubkey instanceof XECPublicKey && privkey instanceof XECPrivateKey) { - pub = ByteUtil.bytesToHex(((XECPublicKey) pubkey).getU().toByteArray(), false); - priv = ByteUtil.bytesToHex(((XECPrivateKey) privkey).getScalar().get(), false); - } else if (pubkey instanceof EdECPublicKey && privkey instanceof EdECPrivateKey) { - pub = ByteUtil.bytesToHex(((EdECPublicKey) pubkey).getPoint().getY().toByteArray(), false); - priv = ByteUtil.bytesToHex(((EdECPrivateKey) privkey).getBytes().get(), false); - } else if (pubkey instanceof XDHPublicKey && privkey instanceof XDHPrivateKey) { - // Special-case BouncyCastle XDH - pub = ByteUtil.bytesToHex(((XDHPublicKey) pubkey).getU().toByteArray(), false); - PrivateKeyInfo pkinfo = PrivateKeyInfo.getInstance(privkey.getEncoded()); - priv = ByteUtil.bytesToHex(ASN1OctetString.getInstance(pkinfo.getPrivateKey().getOctets()).getOctets(), false); - } else if (pubkey instanceof EdDSAPublicKey && privkey instanceof EdDSAPrivateKey) { - // Special-case BouncyCastle EdDSA - pub = ByteUtil.bytesToHex(((EdDSAPublicKey) pubkey).getPointEncoding(), false); - PrivateKeyInfo pkinfo = PrivateKeyInfo.getInstance(privkey.getEncoded()); - priv = ByteUtil.bytesToHex(ASN1OctetString.getInstance(pkinfo.getPrivateKey().getOctets()).getOctets(), false); - } else { + byte[] pubBytes = ECUtil.pubkeyToBytes(pubkey); + byte[] privBytes = ECUtil.privkeyToBytes(privkey); + String pub = ByteUtil.bytesToHex(pubBytes, false); + String priv = ByteUtil.bytesToHex(privBytes, false); + if (pubBytes == null || privBytes == null) { System.err.println(pubkey.getClass().getCanonicalName()); System.err.println(privkey.getClass().getCanonicalName()); break; @@ -801,7 +772,6 @@ public class ECTesterStandalone { private void test() throws TestException, ParserConfigurationException, FileNotFoundException { TestWriter writer = new FileTestWriter(cli.getOptionValue("test.format", "text"), !cli.hasOption("test.quiet"), cli.getOptionValues("test.output")); StandaloneTestSuite suite; - switch (cli.getArg(0).toLowerCase()) { case "test-vectors": suite = new StandaloneTestVectorSuite(writer, cfg, cli); @@ -836,9 +806,9 @@ public class ECTesterStandalone { case "performance": suite = new StandalonePerformanceSuite(writer, cfg, cli); break; - case "default": default: suite = new StandaloneDefaultSuite(writer, cfg, cli); + break; } suite.run(); -- cgit v1.3.1 From e5e8072363c53b155df42238e049d7929b2380f1 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 27 Apr 2024 00:10:57 +0200 Subject: Add EdDSA to standalone CLI. --- .../ectester/standalone/ECTesterStandalone.java | 53 ++++++++++------------ 1 file changed, 25 insertions(+), 28 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 2dc5040..ab7e45b 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -39,12 +39,6 @@ import cz.crcs.ectester.standalone.libs.*; import cz.crcs.ectester.standalone.output.FileTestWriter; import cz.crcs.ectester.standalone.test.suites.*; import org.apache.commons.cli.*; -import org.bouncycastle.asn1.ASN1OctetString; -import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.jcajce.interfaces.EdDSAPrivateKey; -import org.bouncycastle.jcajce.interfaces.EdDSAPublicKey; -import org.bouncycastle.jcajce.interfaces.XDHPrivateKey; -import org.bouncycastle.jcajce.interfaces.XDHPublicKey; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; @@ -62,7 +56,6 @@ import java.security.interfaces.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; -import java.security.spec.NamedParameterSpec; import java.util.*; import java.util.stream.Collectors; @@ -608,17 +601,17 @@ public class ECTesterStandalone { String hashAlgoOut = sigIdent.getHashAlgo() != null ? String.format("[%s]", sigIdent.getHashAlgo()) : ""; out.printf("index;signTime[%s];verifyTime[%s];data;pubW;privS;signature%s;nonce;verified%n", timeUnit, timeUnit, hashAlgoOut); - ECPrivateKey privkey = (ECPrivateKey) ECUtil.loadKey(EC_Consts.PARAMETER_S, cli.getOptionValue("ecdsa.named-private"), cli.getOptionValue("ecdsa.private"), spec); - ECPublicKey pubkey = (ECPublicKey) ECUtil.loadKey(EC_Consts.PARAMETER_W, cli.getOptionValue("ecdsa.named-public"), cli.getOptionValue("ecdsa.public"), spec); + PrivateKey privkey = (ECPrivateKey) ECUtil.loadKey(EC_Consts.PARAMETER_S, cli.getOptionValue("ecdsa.named-private"), cli.getOptionValue("ecdsa.private"), spec); + PublicKey pubkey = (ECPublicKey) ECUtil.loadKey(EC_Consts.PARAMETER_W, cli.getOptionValue("ecdsa.named-public"), cli.getOptionValue("ecdsa.public"), spec); KeyPair one; if (cli.hasOption("ecdsa.fixed")) { one = kpg.genKeyPair(); if (!cli.hasOption("ecdsa.named-private")) { - privkey = (ECPrivateKey) one.getPrivate(); + privkey = one.getPrivate(); } if (!cli.hasOption("ecdsa.named-public")) { - pubkey = (ECPublicKey) one.getPublic(); + pubkey = one.getPublic(); } } @@ -629,10 +622,10 @@ public class ECTesterStandalone { one = kpg.genKeyPair(); if (!cli.hasOption("ecdsa.named-private")) { - privkey = (ECPrivateKey) one.getPrivate(); + privkey = one.getPrivate(); } if (!cli.hasOption("ecdsa.named-public")) { - pubkey = (ECPublicKey) one.getPublic(); + pubkey = one.getPublic(); } } @@ -656,27 +649,31 @@ public class ECTesterStandalone { verifyTime = lib.getLastNativeTiming(); } - String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false); - String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false); + String pub = ByteUtil.bytesToHex(ECUtil.pubkeyToBytes(pubkey), false); + String priv = ByteUtil.bytesToHex(ECUtil.privkeyToBytes(privkey), false); String sign = ByteUtil.bytesToHex(signature, false); String k = ""; - ECParameterSpec kSpec = spec; - if (kSpec == null) { - kSpec = privkey.getParams(); - } - if (kSpec != null) { - // Parse the types out of SignatureIdent. - String hashAlgo = sigIdent.getHashAlgo(); - String sigType = sigIdent.getSigType(); - if (sigType == null) { - sigType = sigIdent.toString(); + if (privkey instanceof ECPrivateKey) { + ECPrivateKey ecPrivateKey = (ECPrivateKey) privkey; + ECParameterSpec kSpec = spec; + if (kSpec == null) { + kSpec = ecPrivateKey.getParams(); } + if (kSpec != null) { + // Parse the types out of SignatureIdent. + String hashAlgo = sigIdent.getHashAlgo(); + String sigType = sigIdent.getSigType(); + if (sigType == null) { + sigType = sigIdent.toString(); + } - BigInteger kValue = ECUtil.recoverSignatureNonce(signature, data, privkey.getS(), kSpec, hashAlgo, sigType); - if (kValue != null) { - k = ByteUtil.bytesToHex(kValue.toByteArray(), false); + BigInteger kValue = ECUtil.recoverSignatureNonce(signature, data, ecPrivateKey.getS(), kSpec, hashAlgo, sigType); + if (kValue != null) { + k = ByteUtil.bytesToHex(kValue.toByteArray(), false); + } } } + out.printf("%d;%d;%d;%s;%s;%s;%s;%s;%d%n", i, signTime, verifyTime, dataString, pub, priv, sign, k, verified ? 1 : 0); } -- cgit v1.3.1 From 2d6081dd3044a1d76a7e30f25d704a42fe8d2411 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 27 Apr 2024 00:24:22 +0200 Subject: Add note about required Java versions. --- .github/workflows/build.yml | 4 ++-- README.md | 5 ++++- common/build.gradle.kts | 2 +- standalone/build.gradle.kts | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8ad7bcd..10769c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,7 +52,7 @@ jobs: strategy: matrix: - java: [ "11", "17", "21" ] + java: [ "15", "17", "21" ] name: Build reader on Java ${{ matrix.java }} steps: - uses: actions/checkout@v4 @@ -88,7 +88,7 @@ jobs: strategy: matrix: - java: [ "17", "21" ] + java: [ "15", "17", "21" ] env: # ffs: https://github.com/adoptium/adoptium-support/issues/485 !!! # also, add the wolfcrypt JNI path diff --git a/README.md b/README.md index f9cbfd7..726be68 100644 --- a/README.md +++ b/README.md @@ -36,12 +36,15 @@ There are three parts of ECTester, the JavaCard applet used for testing, the rea standalone app which tests software libraries. The target platform for ECTester is Linux, but things should work on Windows as well, although testing of standalone libraries will be limited to Java libraries and Microsoft CNG library. +The ECTester parts require different Java versions. Reader and standalone parts require Java >= 15 while the applet build +will be able to target different JavaCard versions based on the Java version, see [this list](https://github.com/martinpaljak/ant-javacard/wiki/JavaCard-SDK-and-JDK-version-compatibility). + To build ECTester simply do: ```bash git submodule update --init --recursive # To initialize submodules (JavaCard SDKs, Microsoft CNG, BoringSSL, ...) ./gradlew :applet:buildJavaCard # To build the applet (cap) -> "applet/build/javacard/applet[221,222,305].cap". ./gradlew :reader:uberJar # To build the reader tool (jar) -> "reader/build/libs/ECTesterReader.jar" -./gradlew :standalone:libs # To build the native library shims. (Necessary +./gradlew :standalone:libs # To build the native library shims. ./gradlew :standalone:uberJar # To build the standalone tool (jar) -> "standalone/build/libs/ECTesterStandalone.jar" ``` The applet comes in several flavors, targeting JavaCard `2.2.1`, `2.2.2` and `3.0.5`. The `2.2.2` and later flavors diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 0aca7fb..1aff0d7 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -23,5 +23,5 @@ dependencies { } java { - sourceCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_15 } \ No newline at end of file diff --git a/standalone/build.gradle.kts b/standalone/build.gradle.kts index f8d7f9b..5ad3fb4 100644 --- a/standalone/build.gradle.kts +++ b/standalone/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { } java { - sourceCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_15 } application { -- cgit v1.3.1 From fd6385d8432bf18e5d94e37fcc4fc7023fb5d0cc Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 27 Apr 2024 00:25:46 +0200 Subject: Java 15 unavailable in CI. --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 10769c1..b39b474 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,7 +52,7 @@ jobs: strategy: matrix: - java: [ "15", "17", "21" ] + java: [ "17", "21", "22" ] name: Build reader on Java ${{ matrix.java }} steps: - uses: actions/checkout@v4 @@ -88,7 +88,7 @@ jobs: strategy: matrix: - java: [ "15", "17", "21" ] + java: [ "17", "21", "22"] env: # ffs: https://github.com/adoptium/adoptium-support/issues/485 !!! # also, add the wolfcrypt JNI path -- cgit v1.3.1 From a2ff9e29a6b4ad49028f4b5ca907e48fe92567b1 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 27 Apr 2024 00:50:52 +0200 Subject: Fix gradle. --- reader/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reader/build.gradle.kts b/reader/build.gradle.kts index 0e8de4e..0386ea5 100644 --- a/reader/build.gradle.kts +++ b/reader/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { } java { - sourceCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_15 } application { -- cgit v1.3.1 From d11222dc25c2a5363b451dd9dbc81482530c9107 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 30 Apr 2024 17:20:02 +0200 Subject: Add way of handling SIGSEGV and SIGABRT in native code. --- .../ectester/standalone/ECTesterStandalone.java | 16 +++- .../crcs/ectester/standalone/libs/jni/SigInfo.java | 80 +++++++++++++++++++ .../standalone/libs/jni/SignalException.java | 18 +++++ .../standalone/libs/jni/TimeoutException.java | 11 +++ .../cz/crcs/ectester/standalone/libs/jni/Makefile | 14 +++- .../crcs/ectester/standalone/libs/jni/c_signals.c | 93 ++++++++++++++++++++++ .../crcs/ectester/standalone/libs/jni/c_signals.h | 58 ++++++++++++++ .../cz/crcs/ectester/standalone/libs/jni/gcrypt.c | 7 ++ 8 files changed, 293 insertions(+), 4 deletions(-) create mode 100644 standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/SigInfo.java create mode 100644 standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/SignalException.java create mode 100644 standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/TimeoutException.java create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h 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 ab7e45b..82c2362 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -36,6 +36,8 @@ import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; import cz.crcs.ectester.standalone.consts.SignatureIdent; import cz.crcs.ectester.standalone.libs.*; +import cz.crcs.ectester.standalone.libs.jni.SignalException; +import cz.crcs.ectester.standalone.libs.jni.TimeoutException; import cz.crcs.ectester.standalone.output.FileTestWriter; import cz.crcs.ectester.standalone.test.suites.*; import org.apache.commons.cli.*; @@ -103,6 +105,9 @@ public class ECTesterStandalone { if (!System.getProperty("os.name").startsWith("Windows")) { FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_timing.so", reqs.resolve("lib_timing.so")); System.load(reqs.resolve("lib_timing.so").toString()); + + FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_signals.so", reqs.resolve("lib_signals.so")); + System.load(reqs.resolve("lib_signals.so").toString()); } List libObjects = new LinkedList<>(); @@ -739,7 +744,16 @@ public class ECTesterStandalone { int amount = Integer.parseInt(cli.getOptionValue("generate.amount", "1")); for (int i = 0; i < amount || amount == 0; ++i) { long elapsed = -System.nanoTime(); - KeyPair kp = kpg.genKeyPair(); + KeyPair kp; + try { + kp = kpg.genKeyPair(); + } catch (SignalException exc) { + System.err.println(exc.getSigInfo()); + continue; + } catch (TimeoutException exc) { + System.err.println(exc); + continue; + } elapsed += System.nanoTime(); if (!lib.getNativeTimingSupport().isEmpty()) { elapsed = lib.getLastNativeTiming(); diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/SigInfo.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/SigInfo.java new file mode 100644 index 0000000..3cb7bad --- /dev/null +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/SigInfo.java @@ -0,0 +1,80 @@ +package cz.crcs.ectester.standalone.libs.jni; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class SigInfo { + + private final int signo; + private final int code; + private final int errno; + private final int pid; + private final int uid; + private final long addr; + private final int status; + private final long band; + private final long sigval; + + public SigInfo(int signo, int code, int errno, int pid, int uid, long addr, int status, long band, long sigval) { + this.signo = signo; + this.code = code; + this.errno = errno; + this.pid = pid; + this.uid = uid; + this.addr = addr; + this.status = status; + this.band = band; + this.sigval = sigval; + } + + public int getSigno() { + return signo; + } + + public int getCode() { + return code; + } + + public int getErrno() { + return errno; + } + + public int getPid() { + return pid; + } + + public int getUid() { + return uid; + } + + public long getAddr() { + return addr; + } + + public int getStatus() { + return status; + } + + public long getBand() { + return band; + } + + public long getSigval() { + return sigval; + } + + @Override + public String toString() { + return "SigInfo{" + + "signo=" + signo + + ", code=" + code + + ", errno=" + errno + + ", pid=" + pid + + ", uid=" + uid + + ", addr=" + addr + + ", status=" + status + + ", band=" + band + + ", sigval=" + sigval + + '}'; + } +} diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/SignalException.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/SignalException.java new file mode 100644 index 0000000..726286e --- /dev/null +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/SignalException.java @@ -0,0 +1,18 @@ +package cz.crcs.ectester.standalone.libs.jni; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class SignalException extends RuntimeException { + + private final SigInfo sigInfo; + + public SignalException(SigInfo sigInfo) { + super("Signal caught."); + this.sigInfo = sigInfo; + } + + public SigInfo getSigInfo() { + return sigInfo; + } +} diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/TimeoutException.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/TimeoutException.java new file mode 100644 index 0000000..c4084b9 --- /dev/null +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/TimeoutException.java @@ -0,0 +1,11 @@ +package cz.crcs.ectester.standalone.libs.jni; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class TimeoutException extends RuntimeException { + + public TimeoutException(String message) { + super(message); + } +} 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 1fa16c0..aef1bd3 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 @@ -4,7 +4,7 @@ CC?=gcc CXX?=g++ -LFLAGS+=-fPIC -shared +LFLAGS+=-fPIC -shared -L "$(JNI_LIBDIR)" -L "$(JNI_LIBDIR)/server" #-ljsig -ljvm CFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. -Wno-deprecated-declarations CXXFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. -Wno-deprecated-declarations @@ -36,12 +36,17 @@ endif ifneq ($(JAVA_HOME),) JNI_INCLUDEDIR ?= $(JAVA_HOME)/include + JNI_LIBDIR ?= $(JAVA_HOME)/lib endif ifeq ($(JNI_INCLUDEDIR),) $(error "Could not determine JNI include dir. Try specifying either JAVA_HOME or JNI_INCLUDEDIR.") endif +ifeq ($(JNI_LIBDIR),) + $(error "Could not determine JNI lib dir. Try specifying either JAVA_HOME or JNI_LIBDIR.") +endif + TARGETTRIPLET := $(shell $(CC) -dumpmachine) ifeq ($(JNI_PLATFORM),) @@ -68,6 +73,9 @@ c_utils.o: c_utils.c lib_timing.so: c_timing.c $(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_timing.so $< +lib_signals.so: c_signals.c + $(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_signals.so $< + cpp_utils.o: cpp_utils.cpp $(CXX) $(CXXFLAGS) -c $< @@ -98,8 +106,8 @@ boringssl.o: boringssl.c # libgcrypt shim gcrypt: gcrypt_provider.so -gcrypt_provider.so: gcrypt.o c_utils.o | lib_timing.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell libgcrypt-config --libs) -l:lib_timing.so +gcrypt_provider.so: gcrypt.o c_utils.o | lib_timing.so lib_signals.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell libgcrypt-config --libs) -l:lib_timing.so -l:lib_signals.so gcrypt.o: gcrypt.c $(CC) $(shell libgcrypt-config --cflags) $(CFLAGS) -c $< diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c new file mode 100644 index 0000000..f4adaa5 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c @@ -0,0 +1,93 @@ +#include "c_utils.h" +#include "c_signals.h" + +#if __linux || __posix + +#include +#include +#include + +// TODO: Handle alarms properly. +// Create a new thread, make it sleep, then send alarm to the main thread. + +static siginfo_t last_siginfo; +static bool initialized = false; +static bool caught = false; +static bool timedout = false; +static jmp_buf *target = NULL; + +void handler(int signo, siginfo_t *info, void *context) { + last_siginfo = *info; + caught = true; + longjmp(*target, 1); +} + +void alarm_handler(int signo) { + timedout = true; +} + +static jmp_buf buf; + +jmp_buf *get_jmpbuf() { + return &buf; +} + +static struct sigaction old_segv; +static struct sigaction old_abrt; +static struct sigaction old_alrm; + +void init_signals(jmp_buf *env) { + struct sigaction action; + action.sa_sigaction = handler; + sigemptyset(&action.sa_mask); + action.sa_flags = SA_SIGINFO; + + sigaction(SIGSEGV, &action, &old_segv); + sigaction(SIGABRT, &action, &old_abrt); + + struct sigaction alarm_action; + alarm_action.sa_handler = alarm_handler; + sigemptyset(&alarm_action.sa_mask); + alarm_action.sa_flags = 0; + sigaction(SIGALRM, &alarm_action, &old_alrm); + + target = env; + initialized = true; + caught = false; + timedout = false; +} + + +void deinit_signals() { + sigaction(SIGSEGV, NULL, &old_segv); + sigaction(SIGABRT, NULL, &old_abrt); + sigaction(SIGALRM, NULL, &old_alrm); + + target = NULL; + initialized = false; +} + +bool get_timedout() { + return timedout; +} + +jobject get_siginfo(JNIEnv *env) { + if (!caught) { + return NULL; + } + + jclass local_siginfo_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/SigInfo"); + jmethodID siginfo_init = (*env)->GetMethodID(env, local_siginfo_class, "", "(IIIIIJIJJ)V"); + return (*env)->NewObject(env, local_siginfo_class, siginfo_init, + (jint) last_siginfo.si_signo, + (jint) last_siginfo.si_code, + (jint) last_siginfo.si_errno, + (jint) last_siginfo.si_pid, + (jint) last_siginfo.si_uid, + (jlong) last_siginfo.si_addr, + (jint) last_siginfo.si_status, + (jlong) last_siginfo.si_band, + (jlong) 0); +} + +#endif \ No newline at end of file diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h new file mode 100644 index 0000000..95fc693 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * + */ +void init_signals(jmp_buf *env); + +/** + * + */ +jmp_buf *get_jmpbuf(); + +/** + * + */ +void deinit_signals(); + +/** + * + */ +bool get_timedout(); + +/** + * + */ +jobject get_siginfo(JNIEnv *env); + + +#define SIG_TRY() init_signals(get_jmpbuf()); \ + if (!setjmp(*get_jmpbuf())) +#define SIG_CATCH() deinit_signals(); +#define SIG_HANDLE(env) do { \ + jobject siginfo = get_siginfo(env); \ + if (siginfo != NULL) { \ + jclass sigexception_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/SignalException"); \ + jmethodID new_sigexception = (*env)->GetMethodID(env, sigexception_class, "", "(Lcz/crcs/ectester/standalone/libs/jni/SigInfo;)V"); \ + jobject sigexception = (*env)->NewObject(env, sigexception_class, new_sigexception, siginfo); \ + (*env)->Throw(env, sigexception); \ + } \ + if (get_timedout()) { \ + jclass timeoutexception_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/TimeoutException"); \ + (*env)->ThrowNew(env, timeoutexception_class, "Operation timed out."); \ + } \ +} while (0) + + + +#ifdef __cplusplus +} +#endif 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 ef62fbf..3df7656 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 @@ -1,5 +1,6 @@ #include "c_utils.h" #include "c_timing.h" +#include "c_signals.h" #include "native.h" #include @@ -276,6 +277,12 @@ static jobject generate_from_sexp(JNIEnv *env, gcry_sexp_t gen_sexp) { gcry_error_t err = gcry_pk_genkey(&key_sexp, gen_sexp); native_timing_stop(); + SIG_TRY() { + //raise(SIGSEGV); + } SIG_CATCH(); + + SIG_HANDLE(env); + if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { throw_new_var(env, "java/security/GeneralSecurityException", "Error generating key. Error: %ui", gcry_err_code(err)); goto release_sexp; -- cgit v1.3.1 From 7e551f5cd6e28787a15287b1efe3630a4c32c826 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 6 May 2024 17:27:25 +0200 Subject: Allow for timeouts in native code. --- .../cz/crcs/ectester/standalone/libs/jni/Makefile | 4 +-- .../crcs/ectester/standalone/libs/jni/c_signals.c | 40 +++++++++++++++++----- .../crcs/ectester/standalone/libs/jni/c_signals.h | 9 ++--- .../cz/crcs/ectester/standalone/libs/jni/gcrypt.c | 6 ---- 4 files changed, 39 insertions(+), 20 deletions(-) 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 aef1bd3..93e1539 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 @@ -74,7 +74,7 @@ lib_timing.so: c_timing.c $(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_timing.so $< lib_signals.so: c_signals.c - $(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_signals.so $< + $(CC) -o $@ -shared $(CFLAGS) -pthread -lpthread -Wl,-soname,lib_signals.so $< cpp_utils.o: cpp_utils.cpp $(CXX) $(CXXFLAGS) -c $< @@ -107,7 +107,7 @@ boringssl.o: boringssl.c gcrypt: gcrypt_provider.so gcrypt_provider.so: gcrypt.o c_utils.o | lib_timing.so lib_signals.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell libgcrypt-config --libs) -l:lib_timing.so -l:lib_signals.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -pthread -lpthread $(shell libgcrypt-config --libs) -l:lib_timing.so -l:lib_signals.so gcrypt.o: gcrypt.c $(CC) $(shell libgcrypt-config --cflags) $(CFLAGS) -c $< diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c index f4adaa5..a1ea9f1 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c @@ -6,29 +6,38 @@ #include #include #include - -// TODO: Handle alarms properly. -// Create a new thread, make it sleep, then send alarm to the main thread. +#include +#include static siginfo_t last_siginfo; static bool initialized = false; static bool caught = false; static bool timedout = false; -static jmp_buf *target = NULL; +static sigjmp_buf buf; +static sigjmp_buf *target = NULL; + +struct timer_arg { + unsigned int timeout; + pthread_t main_thread; +}; +static struct timer_arg ta; +static pthread_t timer_thread; void handler(int signo, siginfo_t *info, void *context) { + //printf("Signal, %i\n", signo); last_siginfo = *info; caught = true; - longjmp(*target, 1); + siglongjmp(*target, 1); } void alarm_handler(int signo) { + //printf("Alarm\n"); timedout = true; + siglongjmp(*target, 1); } -static jmp_buf buf; -jmp_buf *get_jmpbuf() { +sigjmp_buf *get_jmpbuf() { return &buf; } @@ -36,7 +45,14 @@ static struct sigaction old_segv; static struct sigaction old_abrt; static struct sigaction old_alrm; -void init_signals(jmp_buf *env) { +void *timer(void *arg) { + sleep(ta.timeout); + pthread_kill(ta.main_thread, SIGALRM); + return NULL; +} + +void init_signals(sigjmp_buf *env, unsigned int timeout) { + //printf("Initializing signals!\n"); struct sigaction action; action.sa_sigaction = handler; sigemptyset(&action.sa_mask); @@ -55,10 +71,18 @@ void init_signals(jmp_buf *env) { initialized = true; caught = false; timedout = false; + + ta.timeout = timeout; + ta.main_thread = pthread_self(); + + pthread_create(&timer_thread, NULL, timer, (void *)&ta); } void deinit_signals() { + //printf("Deinitializing signals!\n"); + pthread_cancel(timer_thread); + sigaction(SIGSEGV, NULL, &old_segv); sigaction(SIGABRT, NULL, &old_abrt); sigaction(SIGALRM, NULL, &old_alrm); diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h index 95fc693..dec7223 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h @@ -2,6 +2,7 @@ #include #include +#include #ifdef __cplusplus extern "C" @@ -11,12 +12,12 @@ extern "C" /** * */ -void init_signals(jmp_buf *env); +void init_signals(jmp_buf *env, unsigned int timeout); /** * */ -jmp_buf *get_jmpbuf(); +sigjmp_buf *get_jmpbuf(); /** * @@ -34,8 +35,8 @@ bool get_timedout(); jobject get_siginfo(JNIEnv *env); -#define SIG_TRY() init_signals(get_jmpbuf()); \ - if (!setjmp(*get_jmpbuf())) +#define SIG_TRY(timeout) init_signals(get_jmpbuf(), timeout); \ + if (!sigsetjmp(*get_jmpbuf(), 1)) #define SIG_CATCH() deinit_signals(); #define SIG_HANDLE(env) do { \ jobject siginfo = get_siginfo(env); \ 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 3df7656..3ddaef4 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 @@ -277,12 +277,6 @@ static jobject generate_from_sexp(JNIEnv *env, gcry_sexp_t gen_sexp) { gcry_error_t err = gcry_pk_genkey(&key_sexp, gen_sexp); native_timing_stop(); - SIG_TRY() { - //raise(SIGSEGV); - } SIG_CATCH(); - - SIG_HANDLE(env); - if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { throw_new_var(env, "java/security/GeneralSecurityException", "Error generating key. Error: %ui", gcry_err_code(err)); goto release_sexp; -- cgit v1.3.1 From ba84b595ed8c0ae34b8c3540414327f8db3e4a62 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 6 May 2024 18:12:15 +0200 Subject: Add lib_signals to all shims. --- .../cz/crcs/ectester/standalone/libs/jni/Makefile | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) 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 93e1539..dca660f 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 @@ -83,7 +83,7 @@ cpp_utils.o: cpp_utils.cpp # OpenSSL shim openssl: openssl_provider.so -openssl_provider.so: openssl.o c_utils.o | lib_timing.so +openssl_provider.so: openssl.o c_utils.o | lib_timing.so lib_signals.so $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs openssl) -l:lib_timing.so openssl.o: openssl.c @@ -96,8 +96,8 @@ 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_boringssl.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_boringssl.so -l:lib_timing.so +boringssl_provider.so: boringssl.o c_utils.o | lib_timing.so lib_signals.so lib_boringssl.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_boringssl.so -l:lib_timing.so -l:lib_signals.so boringssl.o: boringssl.c $(CC) -I$(PROJECT_ROOT_PATH)/ext/boringssl/include/ $(CFLAGS) -c $< @@ -116,8 +116,8 @@ gcrypt.o: gcrypt.c # Libtomcrypt shim tomcrypt: tomcrypt_provider.so -tomcrypt_provider.so: tomcrypt.o c_utils.o | lib_timing.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt) -l:lib_timing.so +tomcrypt_provider.so: tomcrypt.o c_utils.o | lib_timing.so lib_signals.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt) -l:lib_timing.so -l:lib_signals.so tomcrypt.o: tomcrypt.c $(CC) -DLTM_DESC $(shell pkg-config --cflags libtomcrypt) $(CFLAGS) -c $< @@ -126,8 +126,8 @@ tomcrypt.o: tomcrypt.c # Botan-2 shim botan: botan_provider.so -botan_provider.so: botan.o cpp_utils.o | lib_timing.so - $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs botan-2) -l:lib_timing.so +botan_provider.so: botan.o cpp_utils.o | lib_timing.so lib_signals.so + $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs botan-2) -l:lib_timing.so -l:lib_signals.so botan.o: botan.cpp $(CXX) $(shell pkg-config --cflags botan-2) $(CXXFLAGS) -c $< @@ -140,8 +140,8 @@ 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 - $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs $(CRYPTOPP_NAME)) -l:lib_timing.so +cryptopp_provider.so: cryptopp.o cpp_utils.o | lib_timing.so lib_signals.so + $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs $(CRYPTOPP_NAME)) -l:lib_timing.so -l:lib_signals.so cryptopp.o: cryptopp.cpp $(CXX) $(shell pkg-config --cflags $(CRYPTOPP_NAME)) $(CXXFLAGS) -c $< @@ -153,8 +153,8 @@ 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_mbedtls.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_mbedtls.so -l:lib_timing.so +mbedtls_provider.so: mbedtls.o c_utils.o | lib_timing.so lib_signals.so lib_mbedtls.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_mbedtls.so -l:lib_timing.so -l:lib_signals.so mbedtls.o: mbedtls.c $(CC) -I$(PROJECT_ROOT_PATH)/ext/mbedtls/build/include/ $(CFLAGS) -c $< @@ -166,8 +166,8 @@ 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_ippcp.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_ippcp.so -l:lib_timing.so +ippcp_provider.so: ippcp.o c_utils.o | lib_timing.so lib_signals.so lib_ippcp.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_ippcp.so -l:lib_timing.so -l:lib_signals.so ippcp.o: ippcp.c $(CC) -I$(PROJECT_ROOT_PATH)/ext/ipp-crypto/build/.build/RELEASE/include/ $(CFLAGS) -c $< @@ -176,8 +176,8 @@ ippcp.o: ippcp.c # Nettle shim nettle: nettle_provider.so -nettle_provider.so: nettle.o c_utils.o | lib_timing.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs nettle) -l:lib_timing.so $(shell pkg-config --libs hogweed) -lgmp +nettle_provider.so: nettle.o c_utils.o | lib_timing.so lib_signals.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs nettle) -l:lib_timing.so -l:lib_signals.so $(shell pkg-config --libs hogweed) -lgmp nettle.o: nettle.c $(CC) $(shell pkg-config --cflags nettle) $(shell pkg-config --libs hogweed) -lgmp $(CFLAGS) -c $< @@ -189,8 +189,8 @@ 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_libressl.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_libressl.so -l:lib_timing.so +libressl_provider.so: libressl.o c_utils.o | lib_timing.so lib_signals.so lib_libressl.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_libressl.so -l:lib_timing.so -l:lib_signals.so libressl.o: libressl.c $(CC) -I$(PROJECT_ROOT_PATH)/ext/libressl/build/include/ $(CFLAGS) -c $< -- cgit v1.3.1 From c4980ceb1452488d1fb78627ed16e3a36700ccd4 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 6 May 2024 19:19:29 +0200 Subject: Do not test with Java 22 yet (Gradle does not support it fully). --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b39b474..fea8fe5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,7 +52,7 @@ jobs: strategy: matrix: - java: [ "17", "21", "22" ] + java: [ "17", "21"] name: Build reader on Java ${{ matrix.java }} steps: - uses: actions/checkout@v4 @@ -88,7 +88,7 @@ jobs: strategy: matrix: - java: [ "17", "21", "22"] + java: [ "17", "21"] env: # ffs: https://github.com/adoptium/adoptium-support/issues/485 !!! # also, add the wolfcrypt JNI path -- cgit v1.3.1 From 5c823806439086c486bbddcb1cf79bc17247e24c Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 6 May 2024 19:31:48 +0200 Subject: Add signal handling to BoringSSL. --- .../ectester/standalone/output/TextTestWriter.java | 2 +- .../crcs/ectester/standalone/libs/jni/boringssl.c | 37 +++++++++++++++------- .../crcs/ectester/standalone/libs/jni/c_signals.h | 5 ++- 3 files changed, 30 insertions(+), 14 deletions(-) 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 ba345e7..36ff1af 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 @@ -48,7 +48,7 @@ public class TextTestWriter extends BaseTextTestWriter { StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite; StringBuilder sb = new StringBuilder(); sb.append("═══ ").append(Colors.underline("ECTester version:")).append(" ").append(ECTesterStandalone.VERSION).append(System.lineSeparator()); - sb.append("═══ ").append(Colors.underline("Library:")).append(" ").append(standaloneSuite.getLibrary().name()).append(System.lineSeparator()); + sb.append("═══ ").append(Colors.underline("Library:")).append(" ").append(standaloneSuite.getLibrary().name()).append(" (").append(standaloneSuite.getLibrary().getProvider().getName()).append(")").append(System.lineSeparator()); return sb.toString(); } return ""; diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/boringssl.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/boringssl.c index 4cc95a5..6878549 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/boringssl.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/boringssl.c @@ -1,5 +1,6 @@ #include "c_utils.h" #include "c_timing.h" +#include "c_signals.h" #include "native.h" #include @@ -288,9 +289,12 @@ static jobject generate_from_curve(JNIEnv *env, const EC_GROUP *curve) { EC_KEY *key = EC_KEY_new(); EC_KEY_set_group(key, curve); - native_timing_start(); - int err = EC_KEY_generate_key(key); - native_timing_stop(); + int err = 0; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = EC_KEY_generate_key(key); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (!err) { throw_new(env, "java/security/GeneralSecurityException", "Error generating key, EC_KEY_generate_key."); @@ -430,9 +434,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey jbyteArray result = (*env)->NewByteArray(env, secret_len); jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); - native_timing_start(); - int err = ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL); - native_timing_stop(); + int err = 0; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (err <= 0) { throw_new(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key."); @@ -466,9 +473,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); // TODO: Do more Signatures here, maybe use the EVP interface to get to the hashes easier and not hash manually? - native_timing_start(); - ECDSA_SIG *signature = ECDSA_do_sign((unsigned char *) data_data, data_size, priv); - native_timing_stop(); + ECDSA_SIG *signature = NULL; + SIG_TRY(TIMEOUT) { + native_timing_start(); + signature = ECDSA_do_sign((unsigned char *) data_data, data_size, priv); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); if (!signature) { @@ -508,9 +518,12 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); - native_timing_start(); - int result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub); - native_timing_stop(); + int result = 0; + SIG_TRY(TIMEOUT) { + native_timing_start(); + result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (result < 0) { throw_new(env, "java/security/GeneralSecurityException", "Error verifying, ECDSA_do_verify."); diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h index dec7223..4420a4d 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h @@ -9,6 +9,8 @@ extern "C" { #endif +#define TIMEOUT 5 + /** * */ @@ -51,7 +53,8 @@ jobject get_siginfo(JNIEnv *env); (*env)->ThrowNew(env, timeoutexception_class, "Operation timed out."); \ } \ } while (0) - +#define SIG_CATCH_HANDLE(env) SIG_CATCH(); \ + SIG_HANDLE(env) #ifdef __cplusplus -- cgit v1.3.1 From f8ca335dc6b5c42cd124fca1704c715771d8128c Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 6 May 2024 19:49:11 +0200 Subject: Output full library name in machine-readable test reports. --- .../main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java | 4 ++++ .../main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java | 2 +- .../main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java | 2 +- .../main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) 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 a9a49e9..d9d6749 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 @@ -104,6 +104,10 @@ public abstract class ProviderECLibrary implements ECLibrary { return name; } + public String fullName() { + return name() + " (" + provider.getName() + ")"; + } + public Provider getProvider() { return provider; } 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 36ff1af..c53adb2 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 @@ -48,7 +48,7 @@ public class TextTestWriter extends BaseTextTestWriter { StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite; StringBuilder sb = new StringBuilder(); sb.append("═══ ").append(Colors.underline("ECTester version:")).append(" ").append(ECTesterStandalone.VERSION).append(System.lineSeparator()); - sb.append("═══ ").append(Colors.underline("Library:")).append(" ").append(standaloneSuite.getLibrary().name()).append(" (").append(standaloneSuite.getLibrary().getProvider().getName()).append(")").append(System.lineSeparator()); + sb.append("═══ ").append(Colors.underline("Library:")).append(" ").append(standaloneSuite.getLibrary().fullName()).append(System.lineSeparator()); return sb.toString(); } 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 60751f5..2341fc7 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 @@ -147,7 +147,7 @@ public class XMLTestWriter extends BaseXMLTestWriter { result.setAttribute("ectester", ECTesterStandalone.VERSION); Element name = doc.createElement("name"); - name.setTextContent(standaloneSuite.getLibrary().name()); + name.setTextContent(standaloneSuite.getLibrary().fullName()); result.appendChild(name); return result; } 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 664fa18..66c5e38 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 @@ -116,7 +116,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter { Map result = new LinkedHashMap<>(); result.put("type", "library"); result.put("ectester", ECTesterStandalone.VERSION); - result.put("name", standaloneSuite.getLibrary().name()); + result.put("name", standaloneSuite.getLibrary().fullName()); return result; } return null; -- cgit v1.3.1 From b76b401cf1131cb19764dd6cc88c104b85fb8f1a Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 10:47:02 +0200 Subject: Add signal handling to Crypto++. --- .../crcs/ectester/standalone/libs/jni/c_signals.h | 17 +++++ .../crcs/ectester/standalone/libs/jni/cryptopp.cpp | 79 +++++++++++++--------- .../java/cz/crcs/ectester/standalone/AppTests.java | 8 --- 3 files changed, 63 insertions(+), 41 deletions(-) diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h index 4420a4d..466628a 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h @@ -40,6 +40,22 @@ jobject get_siginfo(JNIEnv *env); #define SIG_TRY(timeout) init_signals(get_jmpbuf(), timeout); \ if (!sigsetjmp(*get_jmpbuf(), 1)) #define SIG_CATCH() deinit_signals(); +#define SIG_DEINIT() deinit_signals(); +#ifdef __cplusplus +#define SIG_HANDLE(env) do { \ + jobject siginfo = get_siginfo(env); \ + if (siginfo != NULL) { \ + jclass sigexception_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/SignalException"); \ + jmethodID new_sigexception = env->GetMethodID(sigexception_class, "", "(Lcz/crcs/ectester/standalone/libs/jni/SigInfo;)V"); \ + jobject sigexception = env->NewObject(sigexception_class, new_sigexception, siginfo); \ + env->Throw((jthrowable) sigexception); \ + } \ + if (get_timedout()) { \ + jclass timeoutexception_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/TimeoutException"); \ + env->ThrowNew(timeoutexception_class, "Operation timed out."); \ + } \ +} while (0) +#else #define SIG_HANDLE(env) do { \ jobject siginfo = get_siginfo(env); \ if (siginfo != NULL) { \ @@ -53,6 +69,7 @@ jobject get_siginfo(JNIEnv *env); (*env)->ThrowNew(env, timeoutexception_class, "Operation timed out."); \ } \ } while (0) +#endif #define SIG_CATCH_HANDLE(env) SIG_CATCH(); \ SIG_HANDLE(env) 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 6ec2060..e5deedb 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 @@ -71,6 +71,7 @@ using CryptoPP::Integer; #include "cpp_utils.hpp" #include "c_timing.h" +#include "c_signals.h" /* * Crypto++: @@ -504,14 +505,17 @@ template jobject generate_from_group(JNIEnv *env, DL_GroupParameters_ typename ECDH::Domain ec_domain(group); SecByteBlock priv(ec_domain.PrivateKeyLength()), pub(ec_domain.PublicKeyLength()); - try { - native_timing_start(); - ec_domain.GenerateKeyPair(rng, priv, pub); - native_timing_stop(); - } catch (Exception & ex) { - throw_new(env, "java/security/GeneralSecurityException", ex.what()); - return nullptr; - } + SIG_TRY(TIMEOUT) { + try { + native_timing_start(); + ec_domain.GenerateKeyPair(rng, priv, pub); + native_timing_stop(); + } catch (Exception & ex) { + SIG_DEINIT(); + throw_new(env, "java/security/GeneralSecurityException", ex.what()); + return nullptr; + } + } SIG_CATCH_HANDLE(env); jbyteArray pub_bytearray = env->NewByteArray(pub.SizeInBytes()); jbyte *pub_bytes = env->GetByteArrayElements(pub_bytearray, nullptr); @@ -587,31 +591,34 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey bool success; std::unique_ptr secret; - try { - std::unique_ptr> ecp_group = fp_group_from_params(env, params); - if (ecp_group == nullptr) { - std::unique_ptr> ec2n_group = f2m_group_from_params(env, params); + SIG_TRY(TIMEOUT) { + try { + std::unique_ptr> ecp_group = fp_group_from_params(env, params); + if (ecp_group == nullptr) { + std::unique_ptr> ec2n_group = f2m_group_from_params(env, params); - ECDH::Domain dh_agreement(*ec2n_group); + ECDH::Domain dh_agreement(*ec2n_group); - secret = std::make_unique(dh_agreement.AgreedValueLength()); - native_timing_start(); - success = dh_agreement.Agree(*secret, private_key, public_key); - native_timing_stop(); + secret = std::make_unique(dh_agreement.AgreedValueLength()); + native_timing_start(); + success = dh_agreement.Agree(*secret, private_key, public_key); + native_timing_stop(); - } else { - ECDH::Domain dh_agreement(*ecp_group); + } else { + ECDH::Domain dh_agreement(*ecp_group); - secret = std::make_unique(dh_agreement.AgreedValueLength()); - native_timing_start(); - success = dh_agreement.Agree(*secret, private_key, public_key); - native_timing_stop(); + secret = std::make_unique(dh_agreement.AgreedValueLength()); + native_timing_start(); + success = dh_agreement.Agree(*secret, private_key, public_key); + native_timing_stop(); + } + } catch (Exception & ex) { + SIG_DEINIT(); + throw_new(env, "java/security/GeneralSecurityException", ex.what()); + return nullptr; } - } catch (Exception & ex) { - throw_new(env, "java/security/GeneralSecurityException", ex.what()); - return nullptr; - } + } SIG_CATCH_HANDLE(env); if (!success) { throw_new(env, "java/security/GeneralSecurityException", "Agreement was unsuccessful."); @@ -642,9 +649,12 @@ jbyteArray sign_message(JNIEnv *env, DL_GroupParameters_EC group, jbyteArray jsize data_length = env->GetArrayLength(data); jbyte *data_bytes = env->GetByteArrayElements(data, nullptr); - native_timing_start(); - size_t len = signer.SignMessage(rng, (byte *)data_bytes, data_length, (byte *)signature.c_str()); - native_timing_stop(); + size_t len; + SIG_TRY(TIMEOUT) { + native_timing_start(); + 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); signature.resize(len); @@ -740,9 +750,12 @@ jboolean verify_message(JNIEnv *env, DL_GroupParameters_EC group, jbyteArray jsize data_length = env->GetArrayLength(data); jbyte *data_bytes = env->GetByteArrayElements(data, nullptr); - native_timing_start(); - bool result = verifier.VerifyMessage((byte *)data_bytes, data_length, sig, sig_len); - native_timing_stop(); + bool result; + SIG_TRY(TIMEOUT) { + native_timing_start(); + result = verifier.VerifyMessage((byte *)data_bytes, data_length, sig, sig_len); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT); return result; 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 7ff2826..8802bb4 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -162,7 +162,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") - @Timeout(20) public void miscSuite(String libName) { String[] args = buildCLIArgs(libName, "miscellaneous", "-q"); if (libName.equals("Botan") || libName.equals("Crypto++")) { @@ -173,7 +172,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") - @Timeout(20) public void twistSuite(String libName) { // TODO: "Nettle" is very broken here for a weird reason. assumeFalse(libName.equals("Nettle")); @@ -187,7 +185,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") - @Timeout(20) public void degenerateSuite(String libName) { // TODO: "Nettle" is very broken here for a weird reason. assumeFalse(libName.equals("Nettle")); @@ -201,7 +198,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") - @Timeout(20) public void edgeCasesSuite(String libName) { // TODO: Crypto++ and tomcrypt is broken here. assumeFalse(libName.equals("Crypto++") || libName.equals("tomcrypt")); @@ -215,7 +211,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") - @Timeout(20) // TODO: This breaks the tests because the libs do all sorts of weird stuff here. @Disabled public void compositeSuite(String libName) { @@ -231,7 +226,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") - @Timeout(20) public void cofactorSuite(String libName) { String[] args = buildCLIArgs(libName, "cofactor", "-q"); if (libName.equals("Botan") || libName.equals("Crypto++")) { @@ -242,7 +236,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") - @Timeout(20) // TODO: This breaks the tests because the libs do all sorts of weird stuff here. @Disabled public void wrongSuite(String libName) { @@ -258,7 +251,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") - @Timeout(20) public void invalidSuite(String libName) { // TODO: "Nettle" is very broken here for a weird reason. assumeFalse(libName.equals("Nettle")); -- cgit v1.3.1 From a765087f0fb9d21eb26780a187dbca23e9267376 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 15:43:18 +0200 Subject: Fix signal restoration in signal handling. --- .../main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c | 6 +++--- standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c index a1ea9f1..dd08bb8 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c @@ -83,9 +83,9 @@ void deinit_signals() { //printf("Deinitializing signals!\n"); pthread_cancel(timer_thread); - sigaction(SIGSEGV, NULL, &old_segv); - sigaction(SIGABRT, NULL, &old_abrt); - sigaction(SIGALRM, NULL, &old_alrm); + sigaction(SIGSEGV, &old_segv, NULL); + sigaction(SIGABRT, &old_abrt, NULL); + sigaction(SIGALRM, &old_alrm, NULL); target = NULL; initialized = false; 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 8802bb4..c94824c 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -2,7 +2,6 @@ package cz.crcs.ectester.standalone; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junitpioneer.jupiter.StdIo; -- cgit v1.3.1 From 910ccecc91097616e407ed85bba91eae80309174 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 16:17:32 +0200 Subject: Disable signal handling in Crypto++. --- .../main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp | 4 ++++ 1 file changed, 4 insertions(+) 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 e5deedb..3590ef2 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 @@ -72,6 +72,10 @@ using CryptoPP::Integer; #include "cpp_utils.hpp" #include "c_timing.h" #include "c_signals.h" +#define SIG_TRY(x) +#define SIG_CATCH_HANDLE(x) +#define SIG_CATCH() +#define SIG_DEINIT() /* * Crypto++: -- cgit v1.3.1 From 2e6207f7d83d9efb8db571ca4f04d79ca63f212f Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 16:24:22 +0200 Subject: Disable bad tests via comment instead of @Disable. --- standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java | 4 ++++ 1 file changed, 4 insertions(+) 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 c94824c..c39ee54 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -208,6 +208,7 @@ public class AppTests { ECTesterStandalone.main(args); } + /* @ParameterizedTest @MethodSource("libs") // TODO: This breaks the tests because the libs do all sorts of weird stuff here. @@ -222,6 +223,7 @@ public class AppTests { } ECTesterStandalone.main(args); } + */ @ParameterizedTest @MethodSource("libs") @@ -233,6 +235,7 @@ public class AppTests { ECTesterStandalone.main(args); } + /* @ParameterizedTest @MethodSource("libs") // TODO: This breaks the tests because the libs do all sorts of weird stuff here. @@ -247,6 +250,7 @@ public class AppTests { } ECTesterStandalone.main(args); } + */ @ParameterizedTest @MethodSource("libs") -- cgit v1.3.1 From 0f26779b0e94a46697f11b5f6262495ec412434c Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 16:25:04 +0200 Subject: Add signal handling to tomcrypt. --- .../crcs/ectester/standalone/libs/jni/tomcrypt.c | 37 +++++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) 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 efaa3b9..9593e9b 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 @@ -1,5 +1,6 @@ #include "c_utils.h" #include "c_timing.h" +#include "c_signals.h" #include "native.h" #include @@ -232,9 +233,12 @@ static void free_curve(ltc_ecc_set_type *curve) { static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) { ecc_key key; - native_timing_start(); - int err = ecc_make_key_ex(<c_prng, find_prng("yarrow"), &key, curve); - native_timing_stop(); + int err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ecc_make_key_ex(<c_prng, find_prng("yarrow"), &key, curve); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (err != CRYPT_OK) { throw_new(env, "java/security/GeneralSecurityException", error_to_string(err)); @@ -381,9 +385,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey unsigned char result[curve->size]; unsigned long output_len = curve->size; - native_timing_start(); - int err = ecc_shared_secret(&priv, &pub, result, &output_len); - native_timing_stop(); + int err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ecc_shared_secret(&priv, &pub, result, &output_len); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (err != CRYPT_OK) { throw_new(env, "java/security/GeneralSecurityException", error_to_string(err)); @@ -425,9 +432,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig unsigned char result[curve->size*4]; unsigned long output_len = curve->size*4; - native_timing_start(); - int err = ecc_sign_hash((unsigned char *) data_data, data_size, result, &output_len, <c_prng, find_prng("yarrow"), &priv); - native_timing_stop(); + int err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ecc_sign_hash((unsigned char *) data_data, data_size, result, &output_len, <c_prng, find_prng("yarrow"), &priv); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (err != CRYPT_OK) { throw_new(env, "java/security/GeneralSecurityException", error_to_string(err)); @@ -467,9 +477,12 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL); int result; - native_timing_start(); - int err = ecc_verify_hash((unsigned char *) sig_data, sig_size, (unsigned char *) data_data, data_size, &result, &pub); - native_timing_stop(); + int err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ecc_verify_hash((unsigned char *) sig_data, sig_size, (unsigned char *) data_data, data_size, &result, &pub); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (err != CRYPT_OK) { throw_new(env, "java/security/GeneralSecurityException", error_to_string(err)); -- cgit v1.3.1 From 568d704359aab7435c92e6a71713ed89564dcef8 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 16:29:51 +0200 Subject: Add signal handling to OpenSSL. --- .../cz/crcs/ectester/standalone/libs/jni/openssl.c | 38 +++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) 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 3fa560e..fc02e9d 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 @@ -1,5 +1,6 @@ #include "c_utils.h" #include "c_timing.h" +#include "c_signals.h" #include "native.h" #include @@ -350,9 +351,12 @@ static jobject generate_from_curve(JNIEnv *env, const EC_GROUP *curve) { EC_KEY *key = EC_KEY_new(); EC_KEY_set_group(key, curve); - native_timing_start(); - int result = EC_KEY_generate_key(key); - native_timing_stop(); + int result; + SIG_TRY(TIMEOUT) { + native_timing_start(); + result = EC_KEY_generate_key(key); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (!result) { throw_new(env, "java/security/GeneralSecurityException", "Error generating key, EC_KEY_generate_key."); @@ -488,9 +492,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey jbyteArray result = (*env)->NewByteArray(env, secret_len); jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); - native_timing_start(); - int err = ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL); - native_timing_stop(); + int err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (err <= 0) { throw_new(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key."); @@ -524,9 +531,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); // TODO: Do more Signatures here, maybe use the EVP interface to get to the hashes easier and not hash manually? - native_timing_start(); - ECDSA_SIG *signature = ECDSA_do_sign((unsigned char *) data_data, data_size, priv); - native_timing_stop(); + ECDSA_SIG *signature; + SIG_TRY(TIMEOUT) { + native_timing_start(); + signature = ECDSA_do_sign((unsigned char *) data_data, data_size, priv); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); if (!signature) { @@ -566,9 +576,13 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); - native_timing_start(); - int result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub); - native_timing_stop(); + int result; + SIG_TRY(TIMEOUT) { + native_timing_start(); + result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); + (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); if (result < 0) { -- cgit v1.3.1 From bcd5077163d34e34d490f26875772fa62a4ee068 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 16:31:54 +0200 Subject: Add signal handling to Nettle. --- .../cz/crcs/ectester/standalone/libs/jni/nettle.c | 36 ++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) 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 dfc8389..48b8f26 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 @@ -1,5 +1,6 @@ #include "c_utils.h" #include "c_timing.h" +#include "c_signals.h" #include "native.h" #include @@ -150,9 +151,12 @@ static jobject generate_from_curve(JNIEnv *env, const struct ecc_curve* curve, j ecc_point_init(&pub, curve); ecc_scalar_init(&priv, curve); - native_timing_start(); - ecdsa_generate_keypair(&pub, &priv, (void *) &yarrow, (nettle_random_func *) yarrow256_random); - native_timing_stop(); + + SIG_TRY(TIMEOUT) { + native_timing_start(); + ecdsa_generate_keypair(&pub, &priv, (void *) &yarrow, (nettle_random_func *) yarrow256_random); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); mpz_t private_value; mpz_init(private_value); @@ -311,9 +315,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey jbyteArray result = (*env)->NewByteArray(env, byte_size); jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); - native_timing_start(); - ecc_point_mul(&resultPoint, &privScalar, &eccPubPoint); - native_timing_stop(); + SIG_TRY(TIMEOUT) { + native_timing_start(); + ecc_point_mul(&resultPoint, &privScalar, &eccPubPoint); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); mpz_t x; mpz_init(x); @@ -461,9 +467,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig struct dsa_signature signature; dsa_signature_init(&signature); - native_timing_start(); - ecdsa_sign(&privScalar, (void *) &yarrow, (nettle_random_func *) yarrow256_random, data_size, (unsigned char*)data_data, &signature); - native_timing_stop(); + SIG_TRY(TIMEOUT) { + native_timing_start(); + ecdsa_sign(&privScalar, (void *) &yarrow, (nettle_random_func *) yarrow256_random, data_size, (unsigned char*)data_data, &signature); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); @@ -515,9 +523,13 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); - native_timing_start(); - int result = ecdsa_verify(&eccPubPoint, data_size, (unsigned char*)data_data, &eccSignature); - native_timing_stop(); + int result; + SIG_TRY(TIMEOUT) { + native_timing_start(); + result = ecdsa_verify(&eccPubPoint, data_size, (unsigned char*)data_data, &eccSignature); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); + (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); ecc_point_clear(&eccPubPoint); -- cgit v1.3.1 From aeaeef42697153a5b1cb9b0b5a64f9495af83157 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 16:46:49 +0200 Subject: Fix OpenSSL build with signals. --- .../src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 dca660f..2354194 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 @@ -84,7 +84,7 @@ cpp_utils.o: cpp_utils.cpp openssl: openssl_provider.so openssl_provider.so: openssl.o c_utils.o | lib_timing.so lib_signals.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs openssl) -l:lib_timing.so + $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs openssl) -l:lib_timing.so -l:lib_signals.so openssl.o: openssl.c $(CC) $(shell pkg-config --cflags openssl) $(CFLAGS) -c $< -- cgit v1.3.1 From 757621b3240482194f66146089dba960eeb5837c Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 17:10:24 +0200 Subject: Add signal handling to mbedTLS. --- .../cz/crcs/ectester/standalone/libs/jni/mbedtls.c | 34 ++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) 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 ab556d8..7a552da 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 @@ -1,5 +1,6 @@ #include "c_utils.h" #include "c_timing.h" +#include "c_signals.h" #include "native.h" #include @@ -315,9 +316,12 @@ static jobject generate_from_curve(JNIEnv *env, mbedtls_ecp_group *group) { } gen_counter++; - native_timing_start(); - int error = mbedtls_ecp_gen_keypair(group, &d, &Q, ctr_drbg_wrapper, &ctr_drbg); - native_timing_stop(); + int error; + SIG_TRY(TIMEOUT) { + native_timing_start(); + error = mbedtls_ecp_gen_keypair(group, &d, &Q, ctr_drbg_wrapper, &ctr_drbg); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (error) { throw_new(env, "java/security/GeneralSecurityException", err_to_string(error)); @@ -453,9 +457,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey mbedtls_mpi result; mbedtls_mpi_init(&result); - native_timing_start(); - error = mbedtls_ecdh_compute_shared(&curve, &result, &pub, &priv, ctr_drbg_wrapper, &ctr_drbg); - native_timing_stop(); + SIG_TRY(TIMEOUT) { + native_timing_start(); + error = mbedtls_ecdh_compute_shared(&curve, &result, &pub, &priv, ctr_drbg_wrapper, &ctr_drbg); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (error) { throw_new(env, "java/security/GeneralSecurityException", err_to_string(error)); @@ -504,9 +510,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); - native_timing_start(); - error = mbedtls_ecdsa_sign(&curve, &r, &s, &priv, (unsigned char *) data_data, data_size, ctr_drbg_wrapper, &ctr_drbg); - native_timing_stop(); + SIG_TRY(TIMEOUT) { + native_timing_start(); + error = mbedtls_ecdsa_sign(&curve, &r, &s, &priv, (unsigned char *) data_data, data_size, ctr_drbg_wrapper, &ctr_drbg); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); mbedtls_mpi_free(&priv); mbedtls_ecp_group_free(&curve); @@ -563,9 +571,11 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); - native_timing_start(); - error = mbedtls_ecdsa_verify(&curve, (unsigned char *) data_data, data_size, &pub, &r, &s); - native_timing_stop(); + SIG_TRY(TIMEOUT) { + native_timing_start(); + error = mbedtls_ecdsa_verify(&curve, (unsigned char *) data_data, data_size, &pub, &r, &s); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); if (error) { -- cgit v1.3.1 From 8454c5781dd0b2ab92666c2f3d2a2bfff102de01 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 17:12:04 +0200 Subject: Add signal handling to LibreSSL. --- .../crcs/ectester/standalone/libs/jni/libressl.c | 38 +++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/libressl.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/libressl.c index 398ad1e..7d50836 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/libressl.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/libressl.c @@ -1,5 +1,6 @@ #include "c_utils.h" #include "c_timing.h" +#include "c_signals.h" #include "native.h" #include @@ -313,9 +314,12 @@ static jobject generate_from_curve(JNIEnv *env, const EC_GROUP *curve) { EC_KEY *key = EC_KEY_new(); EC_KEY_set_group(key, curve); - native_timing_start(); - int err = EC_KEY_generate_key(key); - native_timing_stop(); + int err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = EC_KEY_generate_key(key); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (!err) { throw_new(env, "java/security/GeneralSecurityException", "Error generating key, EC_KEY_generate_key."); @@ -453,9 +457,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey jbyteArray result = (*env)->NewByteArray(env, secret_len); jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); - native_timing_start(); - int err = ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL); - native_timing_stop(); + int err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (err <= 0) { throw_new(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key."); @@ -489,9 +496,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); // TODO: Do more Signatures here, maybe use the EVP interface to get to the hashes easier and not hash manually? - native_timing_start(); - ECDSA_SIG *signature = ECDSA_do_sign((unsigned char *) data_data, data_size, priv); - native_timing_stop(); + ECDSA_SIG *signature; + SIG_TRY(TIMEOUT) { + native_timing_start(); + signature = ECDSA_do_sign((unsigned char *) data_data, data_size, priv); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); if (!signature) { @@ -531,9 +541,13 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); - native_timing_start(); - int result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub); - native_timing_stop(); + int result; + SIG_TRY(TIMEOUT) { + native_timing_start(); + result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); + (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); if (result < 0) { -- cgit v1.3.1 From e3dea615dbdf1170d304f638ab46f51115ce40be Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 17:14:55 +0200 Subject: Add signal handling to ipp-cp. --- .../cz/crcs/ectester/standalone/libs/jni/ippcp.c | 70 +++++++++++++--------- 1 file changed, 43 insertions(+), 27 deletions(-) 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 2f876d2..fbf917e 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 @@ -1,5 +1,6 @@ #include "c_timing.h" #include "c_utils.h" +#include "c_signals.h" #include #include @@ -379,9 +380,12 @@ static jobject generate_from_curve(JNIEnv *env, int keysize, IppsECCPState *curv int ord_bytes = (ord_bits + 7) / 8; IppsBigNumState *secret = new_bn(ord_bits); - native_timing_start(); - IppStatus err = ippsECCPGenKeyPair(secret, point, curve, prng_wrapper, prng_state); - native_timing_stop(); + IppStatus err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ippsECCPGenKeyPair(secret, point, curve, prng_wrapper, prng_state); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (err != ippStsNoErr) { throw_new(env, "java/security/GeneralSecurityException", ippcpGetStatusString(err)); @@ -559,9 +563,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey IppsBigNumState *share = new_bn(keysize); - native_timing_start(); - IppStatus err = ippsECCPSharedSecretDH(priv_bn, pub, share, curve); - native_timing_stop(); + IppStatus err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ippsECCPSharedSecretDH(priv_bn, pub, share, curve); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); free(priv_bn); free(pub); @@ -622,23 +629,29 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jbyte r_buf[ord_bytes]; jbyte s_buf[ord_bytes]; - native_timing_start(); - IppStatus err = ippsECCPGenKeyPair(ephemeral_secret, ephemeral_point, curve, prng_wrapper, prng_state); - if (err != ippStsNoErr) { - throw_new(env, "java/security/GeneralSecurityException", ippcpGetStatusString(err)); - goto error; - } - err = ippsECCPSetKeyPair(ephemeral_secret, ephemeral_point, ippFalse, curve); - if (err != ippStsNoErr) { - throw_new(env, "java/security/GeneralSecurityException", ippcpGetStatusString(err)); - goto error; - } - err = ippsECCPSignDSA(data_bn, priv_bn, r, s, curve); - if (err != ippStsNoErr) { - throw_new(env, "java/security/GeneralSecurityException", ippcpGetStatusString(err)); - goto error; - } - native_timing_stop(); + IppStatus err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = ippsECCPGenKeyPair(ephemeral_secret, ephemeral_point, curve, prng_wrapper, prng_state); + if (err != ippStsNoErr) { + SIG_DEINIT(); + throw_new(env, "java/security/GeneralSecurityException", ippcpGetStatusString(err)); + goto error; + } + err = ippsECCPSetKeyPair(ephemeral_secret, ephemeral_point, ippFalse, curve); + if (err != ippStsNoErr) { + SIG_DEINIT(); + throw_new(env, "java/security/GeneralSecurityException", ippcpGetStatusString(err)); + goto error; + } + err = ippsECCPSignDSA(data_bn, priv_bn, r, s, curve); + if (err != ippStsNoErr) { + SIG_DEINIT(); + throw_new(env, "java/security/GeneralSecurityException", ippcpGetStatusString(err)); + goto error; + } + native_timing_stop(); + } SIG_CATCH_HANDLE(env); bn_get(r, (uint8_t *) r_buf, ord_bytes); bn_get(s, (uint8_t *) s_buf, ord_bytes); @@ -713,10 +726,13 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna IppECResult result; - native_timing_start(); - ippsECCPSetKeyPair(NULL, pub, ippTrue, curve); - IppStatus err = ippsECCPVerifyDSA(data_bn, r, s, &result, curve); - native_timing_stop(); + IppStatus err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + ippsECCPSetKeyPair(NULL, pub, ippTrue, curve); + err = ippsECCPVerifyDSA(data_bn, r, s, &result, curve); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); free(curve); free(pub); -- cgit v1.3.1 From ca1be45c3e39a3d667b0d5a7023958487c8d55a2 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 17:16:25 +0200 Subject: Add signal handling to gcrypt. --- .../cz/crcs/ectester/standalone/libs/jni/gcrypt.c | 37 +++++++++++++++------- 1 file changed, 25 insertions(+), 12 deletions(-) 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 3ddaef4..705a873 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 @@ -273,9 +273,12 @@ static jobject generate_from_sexp(JNIEnv *env, gcry_sexp_t gen_sexp) { jobject result = NULL; gcry_sexp_t key_sexp; - native_timing_start(); - gcry_error_t err = gcry_pk_genkey(&key_sexp, gen_sexp); - native_timing_stop(); + gcry_error_t err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = gcry_pk_genkey(&key_sexp, gen_sexp); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { throw_new_var(env, "java/security/GeneralSecurityException", "Error generating key. Error: %ui", gcry_err_code(err)); @@ -461,9 +464,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey gcry_sexp_t res_sexp; // TODO: figure out why ecc_encrypt_raw takes signed representation.. Nobody uses that., everybody uses unsigned reduced mod p. - native_timing_start(); - gcry_error_t err = gcry_pk_encrypt(&res_sexp, enc_sexp, pub); - native_timing_stop(); + gcry_error_t err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = gcry_pk_encrypt(&res_sexp, enc_sexp, pub); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDH. Error: %ui", gcry_err_code(err)); @@ -573,9 +579,13 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig get_sign_data_sexp(env, &data_sexp, this, data); gcry_sexp_t res_sexp; - native_timing_start(); - gcry_error_t err = gcry_pk_sign(&res_sexp, data_sexp, priv_sexp); - native_timing_stop(); + gcry_error_t err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = gcry_pk_sign(&res_sexp, data_sexp, priv_sexp); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); + if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDSA. Error: %ui", gcry_err_code(err)); goto release_init; @@ -628,9 +638,12 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna gcry_sexp_t sig_sexp; gcry_sexp_build(&sig_sexp, NULL, "(sig-val (ecdsa (r %M) (s %M)))", r_mpi, s_mpi); - native_timing_start(); - gcry_error_t err = gcry_pk_verify(sig_sexp, data_sexp, pub_sexp); - native_timing_stop(); + gcry_error_t err; + SIG_TRY(TIMEOUT) { + native_timing_start(); + err = gcry_pk_verify(sig_sexp, data_sexp, pub_sexp); + native_timing_stop(); + } SIG_CATCH_HANDLE(env); if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { if (gcry_err_code(err) != GPG_ERR_BAD_SIGNATURE) { -- cgit v1.3.1 From 2b80f0abca83172e586ca192e16db00b3951226a Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 17:53:43 +0200 Subject: Attempt to enable signal handling for Cpp, fail. --- .../ectester/standalone/ECTesterStandalone.java | 6 +- .../cz/crcs/ectester/standalone/libs/jni/Makefile | 47 ++++---- .../crcs/ectester/standalone/libs/jni/c_signals.h | 50 ++------- .../ectester/standalone/libs/jni/cpp_signals.cpp | 122 +++++++++++++++++++++ .../ectester/standalone/libs/jni/cpp_signals.hpp | 59 ++++++++++ .../crcs/ectester/standalone/libs/jni/cryptopp.cpp | 7 +- 6 files changed, 228 insertions(+), 63 deletions(-) create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.cpp create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.hpp 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 82c2362..6ef1be7 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -106,8 +106,10 @@ public class ECTesterStandalone { FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_timing.so", reqs.resolve("lib_timing.so")); System.load(reqs.resolve("lib_timing.so").toString()); - FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_signals.so", reqs.resolve("lib_signals.so")); - System.load(reqs.resolve("lib_signals.so").toString()); + FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_csignals.so", reqs.resolve("lib_csignals.so")); + System.load(reqs.resolve("lib_csignals.so").toString()); + FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_cppsignals.so", reqs.resolve("lib_cppsignals.so")); + System.load(reqs.resolve("lib_cppsignals.so").toString()); } List libObjects = new LinkedList<>(); 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 2354194..6282574 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 @@ -73,8 +73,11 @@ c_utils.o: c_utils.c lib_timing.so: c_timing.c $(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_timing.so $< -lib_signals.so: c_signals.c - $(CC) -o $@ -shared $(CFLAGS) -pthread -lpthread -Wl,-soname,lib_signals.so $< +lib_csignals.so: c_signals.c + $(CC) -o $@ -shared $(CFLAGS) -pthread -lpthread -Wl,-soname,lib_csignals.so $< + +lib_cppsignals.so: cpp_signals.cpp + $(CC) -o $@ -shared $(CFLAGS) -pthread -lpthread -Wl,-soname,lib_cppsignals.so $< cpp_utils.o: cpp_utils.cpp $(CXX) $(CXXFLAGS) -c $< @@ -83,8 +86,8 @@ cpp_utils.o: cpp_utils.cpp # OpenSSL shim openssl: openssl_provider.so -openssl_provider.so: openssl.o c_utils.o | lib_timing.so lib_signals.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs openssl) -l:lib_timing.so -l:lib_signals.so +openssl_provider.so: openssl.o c_utils.o | lib_timing.so lib_csignals.so + $(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 $(CC) $(shell pkg-config --cflags openssl) $(CFLAGS) -c $< @@ -96,8 +99,8 @@ 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_signals.so lib_boringssl.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_boringssl.so -l:lib_timing.so -l:lib_signals.so +boringssl_provider.so: boringssl.o c_utils.o | lib_timing.so lib_csignals.so 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 $(CC) -I$(PROJECT_ROOT_PATH)/ext/boringssl/include/ $(CFLAGS) -c $< @@ -106,8 +109,8 @@ boringssl.o: boringssl.c # libgcrypt shim gcrypt: gcrypt_provider.so -gcrypt_provider.so: gcrypt.o c_utils.o | lib_timing.so lib_signals.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -pthread -lpthread $(shell libgcrypt-config --libs) -l:lib_timing.so -l:lib_signals.so +gcrypt_provider.so: gcrypt.o c_utils.o | lib_timing.so lib_csignals.so + $(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 $(CC) $(shell libgcrypt-config --cflags) $(CFLAGS) -c $< @@ -116,8 +119,8 @@ gcrypt.o: gcrypt.c # Libtomcrypt shim tomcrypt: tomcrypt_provider.so -tomcrypt_provider.so: tomcrypt.o c_utils.o | lib_timing.so lib_signals.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt) -l:lib_timing.so -l:lib_signals.so +tomcrypt_provider.so: tomcrypt.o c_utils.o | lib_timing.so lib_csignals.so + $(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 $(CC) -DLTM_DESC $(shell pkg-config --cflags libtomcrypt) $(CFLAGS) -c $< @@ -126,8 +129,8 @@ tomcrypt.o: tomcrypt.c # Botan-2 shim botan: botan_provider.so -botan_provider.so: botan.o cpp_utils.o | lib_timing.so lib_signals.so - $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs botan-2) -l:lib_timing.so -l:lib_signals.so +botan_provider.so: botan.o cpp_utils.o | lib_timing.so lib_cppsignals.so + $(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 $(CXX) $(shell pkg-config --cflags botan-2) $(CXXFLAGS) -c $< @@ -140,8 +143,8 @@ 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_signals.so - $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs $(CRYPTOPP_NAME)) -l:lib_timing.so -l:lib_signals.so +cryptopp_provider.so: cryptopp.o cpp_utils.o | lib_timing.so lib_cppsignals.so + $(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 $(CXX) $(shell pkg-config --cflags $(CRYPTOPP_NAME)) $(CXXFLAGS) -c $< @@ -153,8 +156,8 @@ 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_signals.so lib_mbedtls.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_mbedtls.so -l:lib_timing.so -l:lib_signals.so +mbedtls_provider.so: mbedtls.o c_utils.o | lib_timing.so lib_csignals.so 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 $(CC) -I$(PROJECT_ROOT_PATH)/ext/mbedtls/build/include/ $(CFLAGS) -c $< @@ -166,8 +169,8 @@ 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_signals.so lib_ippcp.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_ippcp.so -l:lib_timing.so -l:lib_signals.so +ippcp_provider.so: ippcp.o c_utils.o | lib_timing.so lib_csignals.so 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 $(CC) -I$(PROJECT_ROOT_PATH)/ext/ipp-crypto/build/.build/RELEASE/include/ $(CFLAGS) -c $< @@ -176,8 +179,8 @@ ippcp.o: ippcp.c # Nettle shim nettle: nettle_provider.so -nettle_provider.so: nettle.o c_utils.o | lib_timing.so lib_signals.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs nettle) -l:lib_timing.so -l:lib_signals.so $(shell pkg-config --libs hogweed) -lgmp +nettle_provider.so: nettle.o c_utils.o | lib_timing.so lib_csignals.so + $(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 $(CC) $(shell pkg-config --cflags nettle) $(shell pkg-config --libs hogweed) -lgmp $(CFLAGS) -c $< @@ -189,8 +192,8 @@ 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_signals.so lib_libressl.so - $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_libressl.so -l:lib_timing.so -l:lib_signals.so +libressl_provider.so: libressl.o c_utils.o | lib_timing.so lib_csignals.so 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 $(CC) -I$(PROJECT_ROOT_PATH)/ext/libressl/build/include/ $(CFLAGS) -c $< diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h index 466628a..3f3c473 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h @@ -4,11 +4,6 @@ #include #include -#ifdef __cplusplus -extern "C" -{ -#endif - #define TIMEOUT 5 /** @@ -41,39 +36,18 @@ jobject get_siginfo(JNIEnv *env); if (!sigsetjmp(*get_jmpbuf(), 1)) #define SIG_CATCH() deinit_signals(); #define SIG_DEINIT() deinit_signals(); -#ifdef __cplusplus -#define SIG_HANDLE(env) do { \ - jobject siginfo = get_siginfo(env); \ - if (siginfo != NULL) { \ - jclass sigexception_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/SignalException"); \ - jmethodID new_sigexception = env->GetMethodID(sigexception_class, "", "(Lcz/crcs/ectester/standalone/libs/jni/SigInfo;)V"); \ - jobject sigexception = env->NewObject(sigexception_class, new_sigexception, siginfo); \ - env->Throw((jthrowable) sigexception); \ - } \ - if (get_timedout()) { \ - jclass timeoutexception_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/TimeoutException"); \ - env->ThrowNew(timeoutexception_class, "Operation timed out."); \ - } \ -} while (0) -#else #define SIG_HANDLE(env) do { \ - jobject siginfo = get_siginfo(env); \ - if (siginfo != NULL) { \ - jclass sigexception_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/SignalException"); \ - jmethodID new_sigexception = (*env)->GetMethodID(env, sigexception_class, "", "(Lcz/crcs/ectester/standalone/libs/jni/SigInfo;)V"); \ - jobject sigexception = (*env)->NewObject(env, sigexception_class, new_sigexception, siginfo); \ - (*env)->Throw(env, sigexception); \ - } \ - if (get_timedout()) { \ - jclass timeoutexception_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/TimeoutException"); \ - (*env)->ThrowNew(env, timeoutexception_class, "Operation timed out."); \ - } \ -} while (0) -#endif + jobject siginfo = get_siginfo(env); \ + if (siginfo != NULL) { \ + jclass sigexception_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/SignalException"); \ + jmethodID new_sigexception = (*env)->GetMethodID(env, sigexception_class, "", "(Lcz/crcs/ectester/standalone/libs/jni/SigInfo;)V"); \ + jobject sigexception = (*env)->NewObject(env, sigexception_class, new_sigexception, siginfo); \ + (*env)->Throw(env, sigexception); \ + } \ + if (get_timedout()) { \ + jclass timeoutexception_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/TimeoutException"); \ + (*env)->ThrowNew(env, timeoutexception_class, "Operation timed out."); \ + } \ + } while (0) #define SIG_CATCH_HANDLE(env) SIG_CATCH(); \ SIG_HANDLE(env) - - -#ifdef __cplusplus -} -#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.cpp new file mode 100644 index 0000000..75bc17c --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.cpp @@ -0,0 +1,122 @@ +#include "cpp_utils.hpp" +#include "cpp_signals.hpp" + +#if __linux || __posix + +#include +#include +#include +#include +#include + +static siginfo_t last_siginfo; +static bool initialized = false; +static bool caught = false; +static bool timedout = false; +static sigjmp_buf buf; +static sigjmp_buf *target = NULL; + +struct timer_arg { + unsigned int timeout; + pthread_t main_thread; +}; +static struct timer_arg ta; +static pthread_t timer_thread; + +extern "C" +{ + +void handler(int signo, siginfo_t *info, void *context) { + //printf("Signal, %i\n", signo); + last_siginfo = *info; + caught = true; + siglongjmp(*target, 1); +} + +void alarm_handler(int signo) { + //printf("Alarm\n"); + timedout = true; + siglongjmp(*target, 1); +} + + +sigjmp_buf *get_jmpbuf() { + return &buf; +} + +static struct sigaction old_segv; +static struct sigaction old_abrt; +static struct sigaction old_alrm; + +void *timer(void *arg) { + sleep(ta.timeout); + pthread_kill(ta.main_thread, SIGALRM); + return NULL; +} + +void init_signals(sigjmp_buf *env, unsigned int timeout) { + //printf("Initializing signals!\n"); + struct sigaction action; + action.sa_sigaction = handler; + sigemptyset(&action.sa_mask); + action.sa_flags = SA_SIGINFO; + + sigaction(SIGSEGV, &action, &old_segv); + sigaction(SIGABRT, &action, &old_abrt); + + struct sigaction alarm_action; + alarm_action.sa_handler = alarm_handler; + sigemptyset(&alarm_action.sa_mask); + alarm_action.sa_flags = 0; + sigaction(SIGALRM, &alarm_action, &old_alrm); + + target = env; + initialized = true; + caught = false; + timedout = false; + + ta.timeout = timeout; + ta.main_thread = pthread_self(); + + pthread_create(&timer_thread, NULL, timer, (void *)&ta); +} + + +void deinit_signals() { + //printf("Deinitializing signals!\n"); + pthread_cancel(timer_thread); + + sigaction(SIGSEGV, &old_segv, NULL); + sigaction(SIGABRT, &old_abrt, NULL); + sigaction(SIGALRM, &old_alrm, NULL); + + target = NULL; + initialized = false; +} + +bool get_timedout() { + return timedout; +} + +jobject get_siginfo(JNIEnv *env) { + if (!caught) { + return NULL; + } + + jclass local_siginfo_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/SigInfo"); + jmethodID siginfo_init = env->GetMethodID(local_siginfo_class, "", "(IIIIIJIJJ)V"); + return env->NewObject(local_siginfo_class, siginfo_init, + (jint) last_siginfo.si_signo, + (jint) last_siginfo.si_code, + (jint) last_siginfo.si_errno, + (jint) last_siginfo.si_pid, + (jint) last_siginfo.si_uid, + (jlong) last_siginfo.si_addr, + (jint) last_siginfo.si_status, + (jlong) last_siginfo.si_band, + (jlong) 0); +} + +} + +#endif \ No newline at end of file diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.hpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.hpp new file mode 100644 index 0000000..b926656 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include + +#define TIMEOUT 5 + +extern "C" +{ + +/** + * + */ +void init_signals(jmp_buf *env, unsigned int timeout); + +/** + * + */ +sigjmp_buf *get_jmpbuf(); + +/** + * + */ +void deinit_signals(); + +/** + * + */ +bool get_timedout(); + +/** + * + */ +jobject get_siginfo(JNIEnv *env); + + +#define SIG_TRY(timeout) init_signals(get_jmpbuf(), timeout); \ + if (!sigsetjmp(*get_jmpbuf(), 1)) +#define SIG_CATCH() deinit_signals(); +#define SIG_DEINIT() deinit_signals(); +#define SIG_HANDLE(env) do { \ + jobject siginfo = get_siginfo(env); \ + if (siginfo != NULL) { \ + jclass sigexception_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/SignalException"); \ + jmethodID new_sigexception = env->GetMethodID(sigexception_class, "", "(Lcz/crcs/ectester/standalone/libs/jni/SigInfo;)V"); \ + jobject sigexception = env->NewObject(sigexception_class, new_sigexception, siginfo); \ + env->Throw((jthrowable) sigexception); \ + } \ + if (get_timedout()) { \ + jclass timeoutexception_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/TimeoutException"); \ + env->ThrowNew(timeoutexception_class, "Operation timed out."); \ + } \ + } while (0) +#define SIG_CATCH_HANDLE(env) SIG_CATCH(); \ + SIG_HANDLE(env) + + +} \ 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 3590ef2..c4c74a6 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 @@ -71,7 +71,12 @@ using CryptoPP::Integer; #include "cpp_utils.hpp" #include "c_timing.h" -#include "c_signals.h" +#include "cpp_signals.hpp" +#undef SIG_TRY +#undef SIG_CATCH_HANDLE +#undef SIG_CATCH +#undef SIG_HANDLE +#undef SIG_DEINIT #define SIG_TRY(x) #define SIG_CATCH_HANDLE(x) #define SIG_CATCH() -- cgit v1.3.1 From 219fb8d3385604070dc2ee9cac5ee7c74bd34749 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 7 May 2024 18:02:22 +0200 Subject: Separatate C and Cpp signal handling. --- .../crcs/ectester/standalone/libs/jni/c_signals.c | 10 +++++----- .../crcs/ectester/standalone/libs/jni/c_signals.h | 22 +++++++++++----------- .../ectester/standalone/libs/jni/cpp_signals.cpp | 10 +++++----- .../ectester/standalone/libs/jni/cpp_signals.hpp | 22 +++++++++++----------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c index dd08bb8..b452787 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.c @@ -37,7 +37,7 @@ void alarm_handler(int signo) { } -sigjmp_buf *get_jmpbuf() { +sigjmp_buf *get_jmpbuf_c() { return &buf; } @@ -51,7 +51,7 @@ void *timer(void *arg) { return NULL; } -void init_signals(sigjmp_buf *env, unsigned int timeout) { +void init_signals_c(sigjmp_buf *env, unsigned int timeout) { //printf("Initializing signals!\n"); struct sigaction action; action.sa_sigaction = handler; @@ -79,7 +79,7 @@ void init_signals(sigjmp_buf *env, unsigned int timeout) { } -void deinit_signals() { +void deinit_signals_c() { //printf("Deinitializing signals!\n"); pthread_cancel(timer_thread); @@ -91,11 +91,11 @@ void deinit_signals() { initialized = false; } -bool get_timedout() { +bool get_timedout_c() { return timedout; } -jobject get_siginfo(JNIEnv *env) { +jobject get_siginfo_c(JNIEnv *env) { if (!caught) { return NULL; } diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h index 3f3c473..a82b572 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_signals.h @@ -9,42 +9,42 @@ /** * */ -void init_signals(jmp_buf *env, unsigned int timeout); +void init_signals_c(jmp_buf *env, unsigned int timeout); /** * */ -sigjmp_buf *get_jmpbuf(); +sigjmp_buf *get_jmpbuf_c(); /** * */ -void deinit_signals(); +void deinit_signals_c(); /** * */ -bool get_timedout(); +bool get_timedout_c(); /** * */ -jobject get_siginfo(JNIEnv *env); +jobject get_siginfo_c(JNIEnv *env); -#define SIG_TRY(timeout) init_signals(get_jmpbuf(), timeout); \ - if (!sigsetjmp(*get_jmpbuf(), 1)) -#define SIG_CATCH() deinit_signals(); -#define SIG_DEINIT() deinit_signals(); +#define SIG_TRY(timeout) init_signals_c(get_jmpbuf_c(), timeout); \ + if (!sigsetjmp(*get_jmpbuf_c(), 1)) +#define SIG_CATCH() deinit_signals_c(); +#define SIG_DEINIT() deinit_signals_c(); #define SIG_HANDLE(env) do { \ - jobject siginfo = get_siginfo(env); \ + jobject siginfo = get_siginfo_c(env); \ if (siginfo != NULL) { \ jclass sigexception_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/SignalException"); \ jmethodID new_sigexception = (*env)->GetMethodID(env, sigexception_class, "", "(Lcz/crcs/ectester/standalone/libs/jni/SigInfo;)V"); \ jobject sigexception = (*env)->NewObject(env, sigexception_class, new_sigexception, siginfo); \ (*env)->Throw(env, sigexception); \ } \ - if (get_timedout()) { \ + if (get_timedout_c()) { \ jclass timeoutexception_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/TimeoutException"); \ (*env)->ThrowNew(env, timeoutexception_class, "Operation timed out."); \ } \ diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.cpp index 75bc17c..999349a 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.cpp +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.cpp @@ -40,7 +40,7 @@ void alarm_handler(int signo) { } -sigjmp_buf *get_jmpbuf() { +sigjmp_buf *get_jmpbuf_cpp() { return &buf; } @@ -54,7 +54,7 @@ void *timer(void *arg) { return NULL; } -void init_signals(sigjmp_buf *env, unsigned int timeout) { +void init_signals_cpp(sigjmp_buf *env, unsigned int timeout) { //printf("Initializing signals!\n"); struct sigaction action; action.sa_sigaction = handler; @@ -82,7 +82,7 @@ void init_signals(sigjmp_buf *env, unsigned int timeout) { } -void deinit_signals() { +void deinit_signals_cpp() { //printf("Deinitializing signals!\n"); pthread_cancel(timer_thread); @@ -94,11 +94,11 @@ void deinit_signals() { initialized = false; } -bool get_timedout() { +bool get_timedout_cpp() { return timedout; } -jobject get_siginfo(JNIEnv *env) { +jobject get_siginfo_cpp(JNIEnv *env) { if (!caught) { return NULL; } diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.hpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.hpp index b926656..4dc222f 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.hpp +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cpp_signals.hpp @@ -12,42 +12,42 @@ extern "C" /** * */ -void init_signals(jmp_buf *env, unsigned int timeout); +void init_signals_cpp(jmp_buf *env, unsigned int timeout); /** * */ -sigjmp_buf *get_jmpbuf(); +sigjmp_buf *get_jmpbuf_cpp(); /** * */ -void deinit_signals(); +void deinit_signals_cpp(); /** * */ -bool get_timedout(); +bool get_timedout_cpp(); /** * */ -jobject get_siginfo(JNIEnv *env); +jobject get_siginfo_cpp(JNIEnv *env); -#define SIG_TRY(timeout) init_signals(get_jmpbuf(), timeout); \ - if (!sigsetjmp(*get_jmpbuf(), 1)) -#define SIG_CATCH() deinit_signals(); -#define SIG_DEINIT() deinit_signals(); +#define SIG_TRY(timeout) init_signals_cpp(get_jmpbuf_cpp(), timeout); \ + if (!sigsetjmp(*get_jmpbuf_cpp(), 1)) +#define SIG_CATCH() deinit_signals_cpp(); +#define SIG_DEINIT() deinit_signals_cpp(); #define SIG_HANDLE(env) do { \ - jobject siginfo = get_siginfo(env); \ + jobject siginfo = get_siginfo_cpp(env); \ if (siginfo != NULL) { \ jclass sigexception_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/SignalException"); \ jmethodID new_sigexception = env->GetMethodID(sigexception_class, "", "(Lcz/crcs/ectester/standalone/libs/jni/SigInfo;)V"); \ jobject sigexception = env->NewObject(sigexception_class, new_sigexception, siginfo); \ env->Throw((jthrowable) sigexception); \ } \ - if (get_timedout()) { \ + if (get_timedout_cpp()) { \ jclass timeoutexception_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/TimeoutException"); \ env->ThrowNew(timeoutexception_class, "Operation timed out."); \ } \ -- cgit v1.3.1 From ba76bd7c04a94b52f57eda418e270dc658976c12 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 10 May 2024 16:08:43 +0200 Subject: Fix Nettle issues. Fixes #23. --- .../java/cz/crcs/ectester/common/util/ECUtil.java | 11 ++ .../crcs/ectester/standalone/libs/NettleLib.java | 32 +++++ .../standalone/libs/jni/NativeKeyAgreementSpi.java | 128 +++++++++++-------- .../libs/jni/NativeKeyPairGeneratorSpi.java | 49 ++++++-- .../cz/crcs/ectester/standalone/libs/jni/native.h | 136 +++++++++++++++++++++ .../cz/crcs/ectester/standalone/libs/jni/nettle.c | 51 +------- .../java/cz/crcs/ectester/standalone/AppTests.java | 15 --- 7 files changed, 294 insertions(+), 128 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java index 74fccc9..54c5131 100644 --- a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java +++ b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java @@ -507,4 +507,15 @@ public class ECUtil { priv.getParams().getGenerator().equals(pub.getParams().getGenerator()) && priv.getParams().getOrder().equals(pub.getParams().getOrder()); } + + public static boolean equalECParameterSpec(ECParameterSpec left, ECParameterSpec right) { + if (left == null || right == null) { + return false; + } + + return left.getCofactor() == right.getCofactor() && + left.getCurve().equals(right.getCurve()) && + left.getGenerator().equals(right.getGenerator()) && + left.getOrder().equals(right.getOrder()); + } } 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 6b60779..d4df414 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 @@ -1,6 +1,15 @@ package cz.crcs.ectester.standalone.libs; +import cz.crcs.ectester.common.ec.EC_Curve; +import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.data.EC_Store; + +import java.security.InvalidAlgorithmParameterException; import java.security.Provider; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.util.Arrays; import java.util.Set; /** @@ -17,4 +26,27 @@ public class NettleLib extends NativeECLibrary { @Override public native Set getCurves(); + + public static ECGenParameterSpec parametersKnown(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { + if (params instanceof ECGenParameterSpec) { + if (Arrays.asList("secp192r1", "secp224r1", "secp256r1", "secp384r1", "secp521r1").contains(((ECGenParameterSpec) params).getName())) { + return (ECGenParameterSpec) params; + } + } else if (params instanceof ECParameterSpec) { + ECParameterSpec spec = (ECParameterSpec) params; + EC_Store store = EC_Store.getInstance(); + if (ECUtil.equalECParameterSpec(spec, store.getObject(EC_Curve.class, "secg/secp192r1").toSpec())) { + return new ECGenParameterSpec("secp192r1"); + } else if (ECUtil.equalECParameterSpec(spec, store.getObject(EC_Curve.class, "secg/secp224r1").toSpec())) { + return new ECGenParameterSpec("secp224r1"); + } else if (ECUtil.equalECParameterSpec(spec, store.getObject(EC_Curve.class, "secg/secp256r1").toSpec())) { + return new ECGenParameterSpec("secp256r1"); + } else if (ECUtil.equalECParameterSpec(spec, store.getObject(EC_Curve.class, "secg/secp384r1").toSpec())) { + return new ECGenParameterSpec("secp384r1"); + } else if (ECUtil.equalECParameterSpec(spec, store.getObject(EC_Curve.class, "secg/secp521r1").toSpec())) { + return new ECGenParameterSpec("secp521r1"); + } + } + throw new InvalidAlgorithmParameterException("Unknown curve."); + } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java index afed02b..d9a4d40 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java @@ -1,6 +1,9 @@ package cz.crcs.ectester.standalone.libs.jni; +import cz.crcs.ectester.common.ec.EC_Curve; import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.standalone.libs.NettleLib; import javax.crypto.KeyAgreementSpi; import javax.crypto.SecretKey; @@ -11,7 +14,6 @@ import java.security.interfaces.ECPublicKey; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; -import java.security.spec.InvalidParameterSpecException; /** * @author Jan Jancar johny@neuromancer.sk @@ -61,6 +63,22 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { return secret.length; } + protected byte[] getPubkey() { + if (publicKey instanceof NativeECPublicKey) { + return ((NativeECPublicKey) publicKey).getData(); + } else { + return ECUtil.pubkeyToBytes(publicKey); + } + } + + protected byte[] getPrivkey() { + if (privateKey instanceof NativeECPrivateKey) { + return ((NativeECPrivateKey) privateKey).getData(); + } else { + return ECUtil.privkeyToBytes(privateKey); + } + } + private abstract static class SimpleKeyAgreementSpi extends NativeKeyAgreementSpi { @Override @@ -72,51 +90,79 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { this.params = params; } - private byte[] getPubkey() { - if (publicKey instanceof NativeECPublicKey) { - return ((NativeECPublicKey) publicKey).getData(); - } else { - return ECUtil.toX962Uncompressed(publicKey.getW(), ((ECParameterSpec) params)); + @Override + protected byte[] engineGenerateSecret() throws IllegalStateException { + return generateSecret(getPubkey(), getPrivkey(), (ECParameterSpec) params); + } + + abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); + + @Override + protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException { + if (algorithm == null) { + throw new NoSuchAlgorithmException("Algorithm must not be null."); } + return generateSecret(getPubkey(), getPrivkey(), (ECParameterSpec) params, algorithm); } - private byte[] getPrivkey() { - if (privateKey instanceof NativeECPrivateKey) { - return ((NativeECPrivateKey) privateKey).getData(); - } else { - return ECUtil.toByteArray(privateKey.getS(), ((ECParameterSpec) params).getOrder().bitLength()); + abstract SecretKey generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params, String algorithm); + } + + private abstract static class ExtendedKeyAgreementSpi extends NativeKeyAgreementSpi { + + @Override + protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { + if (!(params instanceof ECParameterSpec || params instanceof ECGenParameterSpec)) { + throw new InvalidAlgorithmParameterException("Unknown parameter class."); } + engineInit(key, random); + this.params = params; } @Override protected byte[] engineGenerateSecret() throws IllegalStateException { - return generateSecret(getPubkey(), getPrivkey(), (ECParameterSpec) params); + return generateSecret(publicKey, privateKey, params); } - abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); + abstract byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params); @Override protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException { if (algorithm == null) { throw new NoSuchAlgorithmException("Algorithm must not be null"); } - return generateSecret(getPubkey(), getPrivkey(), (ECParameterSpec) params, algorithm); + return generateSecret(publicKey, privateKey, params, algorithm); } - abstract SecretKey generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params, String algorithm); + abstract SecretKey generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params, String algorithm); } - private abstract static class ExtendedKeyAgreementSpi extends NativeKeyAgreementSpi { + private abstract static class NamedKeyAgreementSpi extends NativeKeyAgreementSpi { + + @Override + protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException { + if (!(key instanceof ECPrivateKey)) { + throw new InvalidKeyException("Key must be instance of ECPrivateKey"); + } + privateKey = (ECPrivateKey) key; + try { + this.params = parametersKnown(privateKey.getParams()); + } catch (InvalidAlgorithmParameterException e) { + throw new InvalidKeyException(e); + } + } @Override protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { if (!(params instanceof ECParameterSpec || params instanceof ECGenParameterSpec)) { - throw new InvalidAlgorithmParameterException(); + throw new InvalidAlgorithmParameterException("Unknown parameter class."); } engineInit(key, random); - this.params = params; + this.params = parametersKnown(params); } + abstract ECGenParameterSpec parametersKnown(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException; + @Override protected byte[] engineGenerateSecret() throws IllegalStateException { return generateSecret(publicKey, privateKey, params); @@ -374,7 +420,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { } } - public abstract static class Nettle extends SimpleKeyAgreementSpi { + public abstract static class Nettle extends NamedKeyAgreementSpi { private final String type; public Nettle(String type) { @@ -382,43 +428,21 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { } @Override - byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params) { - try { - // TODO: OMG remove this monstrosity. - AlgorithmParameters tmp = AlgorithmParameters.getInstance("EC"); - tmp.init(params); - ECGenParameterSpec spec = tmp.getParameterSpec(ECGenParameterSpec.class); - switch (spec.getName()) { - case "1.2.840.10045.3.1.7": - spec = new ECGenParameterSpec("secp256r1"); - break; - case "1.2.840.10045.3.1.1": - spec = new ECGenParameterSpec("secp192r1"); - break; - case "1.3.132.0.33": - spec = new ECGenParameterSpec("secp224r1"); - break; - case "1.3.132.0.34": - spec = new ECGenParameterSpec("secp384r1"); - break; - case "1.3.132.0.35": - spec = new ECGenParameterSpec("secp521r1"); - break; - default: - return null; - - } - return generateSecret(pubkey, privkey, spec); - - } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) { - return null; - } + ECGenParameterSpec parametersKnown(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { + return NettleLib.parametersKnown(params); } - native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECGenParameterSpec params); + @Override + byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params) { + return generateSecret(getPubkey(), getPrivkey(), (ECGenParameterSpec) params); + } @Override - native SecretKey generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params, String algorithm); + SecretKey generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params, String algorithm) { + throw new UnsupportedOperationException("Not supported."); + } + + native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECGenParameterSpec params); } public static class NettleECDH extends Nettle { diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java index 0a9487f..086c2c4 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java @@ -2,6 +2,7 @@ package cz.crcs.ectester.standalone.libs.jni; import cz.crcs.ectester.common.ec.EC_Curve; import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.standalone.libs.NettleLib; import java.security.*; import java.security.spec.AlgorithmParameterSpec; @@ -293,7 +294,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { @Override native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random); } - + public static class Libressl extends NativeKeyPairGeneratorSpi { public Libressl() { @@ -319,26 +320,48 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { } @Override - native boolean keysizeSupported(int keysize); + boolean keysizeSupported(int keysize) { + switch (keysize) { + case 192, 224, 256, 384, 521: + return true; + default: + return false; + } + } @Override - native boolean paramsSupported(AlgorithmParameterSpec params); + boolean paramsSupported(AlgorithmParameterSpec params) { + try { + NettleLib.parametersKnown(params); + return true; + } catch (InvalidAlgorithmParameterException ignored) { + return false; + } + } @Override - native KeyPair generate(int keysize, SecureRandom random); + KeyPair generate(int keysize, SecureRandom random) { + EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, "secg/secp" + keysize + "r1"); + return generate(keysize, random, curve.toSpec()); + } + + native KeyPair generate(int keysize, SecureRandom random, AlgorithmParameterSpec spec); @Override KeyPair generate(AlgorithmParameterSpec params, SecureRandom random) { - if (params instanceof ECGenParameterSpec) { - String curveName = ((ECGenParameterSpec) params).getName(); - if (curveName.contains("secp")) { - curveName = "secg/" + curveName; - } - EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName); - ECParameterSpec spec = curve.toSpec(); - return generate(params, random, spec); + ECGenParameterSpec named; + try { + named = NettleLib.parametersKnown(params); + } catch (InvalidAlgorithmParameterException ignored) { + return null; + } + String curveName = named.getName(); + if (curveName.startsWith("secp")) { + curveName = "secg/" + curveName; } - return null; + EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName); + ECParameterSpec spec = curve.toSpec(); + return generate(params, random, spec); } native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random, AlgorithmParameterSpec spec); 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 dcaf57c..60c59b1 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 @@ -1861,3 +1861,139 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } #endif #endif +/* Header for class cz_crcs_ectester_standalone_libs_NettleLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_NettleLib +#define _Included_cz_crcs_ectester_standalone_libs_NettleLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_NettleLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_NettleLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_serialVersionUID 1421746759512286392LL +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_serialVersionUID 4112578634029874840LL +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle_serialVersionUID -4298000515446427739LL +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Nettle + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Nettle_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Nettle */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Nettle +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Nettle +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Nettle_DEFAULT_KEYSIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Nettle_DEFAULT_KEYSIZE 256L +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Nettle + * Method: generate + * Signature: (ILjava/security/SecureRandom;Ljava/security/spec/AlgorithmParameterSpec;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Nettle_generate__ILjava_security_SecureRandom_2Ljava_security_spec_AlgorithmParameterSpec_2 + (JNIEnv *, jobject, jint, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Nettle + * Method: generate + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;Ljava/security/spec/AlgorithmParameterSpec;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Nettle_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2Ljava_security_spec_AlgorithmParameterSpec_2 + (JNIEnv *, jobject, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Nettle */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Nettle +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Nettle +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Nettle + * Method: generateSecret + * Signature: ([B[BLjava/security/spec/ECGenParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Nettle_generateSecret + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Nettle */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Nettle +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Nettle +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Nettle + * Method: sign + * Signature: ([B[BLjava/security/spec/ECGenParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Nettle_sign + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Nettle + * Method: verify + * Signature: ([B[B[BLjava/security/spec/ECGenParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Nettle_verify + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#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 48b8f26..24ba699 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 @@ -36,7 +36,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_create } JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Nettle_setup(JNIEnv *env, jobject self) { - INIT_PROVIDER(env, provider_class); ADD_KPG(env, self, "EC", "Nettle"); ADD_KA(env, self, "ECDH", "NettleECDH"); @@ -67,16 +66,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCur return result; } -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Nettle_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { - int supported[] = {192, 224, 256, 384, 521}; - for (int i = 0; i < 5; i++) { - if (keysize == supported[i]) { - return JNI_TRUE; - } - } - return JNI_FALSE; -} - static const struct ecc_curve* create_curve_from_name(JNIEnv *env, const char* curve_name) { if (!curve_name) { return NULL; @@ -116,34 +105,6 @@ static const struct ecc_curve* create_curve_from_size(JNIEnv *env, jint keysize) } } -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Nettle_paramsSupported(JNIEnv *env, jobject self, jobject params){ - if (params == NULL) { - return JNI_FALSE; - } - - if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { - return JNI_FALSE; - } else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) { - jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;"); - jstring name = (*env)->CallObjectMethod(env, params, get_name); - const char *utf_name = (*env)->GetStringUTFChars(env, name, NULL); - - char *curve_name[5] = {"secp192r1", "secp224r1", "secp256r1", "secp384r1", "secp521r1"}; - for (int i = 0; i < sizeof(curve_name); i++) { - if (strcasecmp(utf_name, curve_name[i]) == 0) { - (*env)->ReleaseStringUTFChars(env, name, utf_name); - return JNI_TRUE; - } - } - (*env)->ReleaseStringUTFChars(env, name, utf_name); - return JNI_FALSE; - } else { - return JNI_FALSE; - } - return JNI_FALSE; - -} - static jobject generate_from_curve(JNIEnv *env, const struct ecc_curve* curve, jobject spec, int byte_size) { struct ecc_point pub; @@ -210,16 +171,15 @@ static jobject generate_from_curve(JNIEnv *env, const struct ecc_curve* curve, j return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Nettle_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Nettle_generate__ILjava_security_SecureRandom_2Ljava_security_spec_AlgorithmParameterSpec_2(JNIEnv *env, jobject self, jint keysize, jobject random, jobject spec) { const struct ecc_curve* curve = create_curve_from_size(env, keysize); if (!curve) { throw_new(env, "java/lang/UnsupportedOperationException", "Not supported."); return NULL; } int byte_size = (keysize + 7) / 8; - jobject result = generate_from_curve(env, curve, NULL, byte_size); + jobject result = generate_from_curve(env, curve, spec, byte_size); return result; - return NULL; } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Nettle_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2Ljava_security_spec_AlgorithmParameterSpec_2(JNIEnv *env, jobject self, jobject params, jobject random, jobject spec) { @@ -280,7 +240,7 @@ int barray_to_privkey(JNIEnv *env, struct ecc_scalar* privKey, jbyteArray priv) return priv_len; } -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Nettle_generateSecret___3B_3BLjava_security_spec_ECGenParameterSpec_2(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Nettle_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;"); jstring name = (*env)->CallObjectMethod(env, params, get_name); const char* utf_name = (*env)->GetStringUTFChars(env, name, NULL); @@ -339,11 +299,6 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey return result; } -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Nettle_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2Ljava_lang_String_2(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params, jstring algorithm) { - throw_new(env, "java/lang/UnsupportedOperationException", "Not supported."); - return NULL; -} - // credit to https://github.com/crocs-muni/ECTester/blob/master/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c size_t signature_to_der(struct dsa_signature* signature, unsigned char *result, int byte_size) { size_t r_tmpSize; 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 c39ee54..1f82bb0 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -90,9 +90,6 @@ public class AppTests { @MethodSource("libs") @StdIo() public void defaultSuite(String libName, StdOut out) { - // TODO: "Nettle" is very broken here for a weird reason. - assumeFalse(libName.equals("Nettle")); - String[] args = buildCLIArgs(libName, "default"); if (libName.equals("Botan") || libName.equals("Crypto++")) { args = buildCLIArgs(libName, "default", "--kpg-type", "ECDH"); @@ -123,9 +120,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") public void performanceSuite(String libName) { - // TODO: "Nettle" is very broken here for a weird reason. - assumeFalse(libName.equals("Nettle")); - String[] args = buildCLIArgs(libName, "performance"); if (libName.equals("Botan") || libName.equals("Crypto++")) { args = buildCLIArgs(libName, "performance", "--kpg-type", "ECDH"); @@ -172,9 +166,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") public void twistSuite(String libName) { - // TODO: "Nettle" is very broken here for a weird reason. - assumeFalse(libName.equals("Nettle")); - String[] args = buildCLIArgs(libName, "twist", "-q"); if (libName.equals("Botan") || libName.equals("Crypto++")) { args = buildCLIArgs(libName, "twist", "--kpg-type", "ECDH", "-q"); @@ -185,9 +176,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") public void degenerateSuite(String libName) { - // TODO: "Nettle" is very broken here for a weird reason. - assumeFalse(libName.equals("Nettle")); - String[] args = buildCLIArgs(libName, "degenerate", "-q"); if (libName.equals("Botan") || libName.equals("Crypto++")) { args = buildCLIArgs(libName, "degenerate", "--kpg-type", "ECDH", "-q"); @@ -255,9 +243,6 @@ public class AppTests { @ParameterizedTest @MethodSource("libs") public void invalidSuite(String libName) { - // TODO: "Nettle" is very broken here for a weird reason. - assumeFalse(libName.equals("Nettle")); - String[] args = buildCLIArgs(libName, "invalid", "-q"); if (libName.equals("Botan") || libName.equals("Crypto++")) { args = buildCLIArgs(libName, "invalid", "--kpg-type", "ECDH", "-q"); -- cgit v1.3.1 From 9a16c642af2ca81b12b4545a7227b3746639e4d0 Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 14 May 2024 14:23:44 +0200 Subject: The signature test vectors are for SHA1 only, check this in standalone. --- .../ectester/standalone/test/suites/StandaloneSignatureSuite.java | 4 ++++ 1 file changed, 4 insertions(+) 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 94e810e..bafaa90 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 @@ -73,6 +73,10 @@ public class StandaloneSignatureSuite extends StandaloneTestSuite { } private void ecdsaTest(EC_SigResult sig, SignatureIdent sigIdent, Result.ExpectedValue expected, byte[] defaultData) throws NoSuchAlgorithmException { + if (!sig.getSig().equals(sigIdent.getHashAlgo())) { + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "ECDSA test of " + sig.getId() + " not applicable.")); + return; + } ECPublicKey ecpub = ECUtil.toPublicKey(EC_Store.getInstance().getObject(EC_Key.Public.class, sig.getVerifyKey())); byte[] data = sig.getSigData(); -- cgit v1.3.1 From e72ea6b90f236927c8f43da3e296290222e46f7b Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 16 May 2024 17:21:11 +0200 Subject: Fix applet selection that was broken in AID suffix change. --- reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java b/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java index 9ba9890..91f4653 100644 --- a/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java +++ b/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java @@ -73,7 +73,7 @@ public class ECTesterReader { private static String CLI_HEADER; private static String CLI_FOOTER = "\n" + LICENSE; - private static final byte[] SELECT_PREFIX = {(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x0c}; + private static final byte[] SELECT_PREFIX = {(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x0f}; private static final byte[] AID_PREFIX = {(byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72}; private static final byte[] AID_CURRENT_VERSION = {(byte) 0x30, (byte) 0x33, (byte) 0x33}; // VERSION v0.3.3 private static final byte[] AID_SUFFIX_221 = {(byte) 0x20, (byte) 0x32, (byte) 0x32, (byte) 0x31}; -- cgit v1.3.1 From b6ea0edd26ff6873d3596c68523d27c6e528a034 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 20 May 2024 12:26:26 +0200 Subject: Add way of selecting tests in Standalone. --- .../ectester/standalone/ECTesterStandalone.java | 37 ++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 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 6ef1be7..2b9a853 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -785,7 +785,40 @@ public class ECTesterStandalone { private void test() throws TestException, ParserConfigurationException, FileNotFoundException { TestWriter writer = new FileTestWriter(cli.getOptionValue("test.format", "text"), !cli.hasOption("test.quiet"), cli.getOptionValues("test.output")); StandaloneTestSuite suite; - switch (cli.getArg(0).toLowerCase()) { + String suiteOpt = cli.getArg(0) != null ? cli.getArg(0).toLowerCase() : "default"; + String testSuite; + int testFrom; + int testTo; + if (suiteOpt.contains(":")) { + String[] parts = suiteOpt.split(":"); + if (parts.length < 2 || parts.length > 3) { + System.err.println("Invalid test suite selection."); + return; + } + testSuite = parts[0]; + try { + testFrom = Integer.parseInt(parts[1]); + } catch (NumberFormatException nfe) { + System.err.println("Invalid test_from number: " + parts[1] + "."); + return; + } + if (parts.length == 3) { + try { + testTo = Integer.parseInt(parts[2]); + } catch (NumberFormatException nfe) { + System.err.println("Invalid test_to number: " + parts[2] + "."); + return; + } + } else { + testTo = -1; + } + } else { + testSuite = suiteOpt; + testFrom = 0; + testTo = -1; + } + + switch (testSuite) { case "test-vectors": suite = new StandaloneTestVectorSuite(writer, cfg, cli); break; @@ -824,7 +857,7 @@ public class ECTesterStandalone { break; } - suite.run(); + suite.run(testFrom, testTo); } /** -- cgit v1.3.1 From 025d1f9db13e8eb72f28b743e5a8884b6d259a24 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 20 May 2024 13:37:10 +0200 Subject: Fix bad param value in standalone wrong test suite. --- common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java b/common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java index eafcb72..1fe6eb0 100644 --- a/common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java +++ b/common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java @@ -19,7 +19,7 @@ public class CustomECFieldFp extends ECFieldFp { @Override public int getFieldSize() { - return p.bitCount(); + return p.bitLength(); } @Override -- cgit v1.3.1 From 0bc459385a67f0a0f09abda7c1c768fc14e20a5f Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 20 May 2024 13:37:35 +0200 Subject: Add check for a=-3 in tomcrypt. --- .../cz/crcs/ectester/standalone/libs/jni/tomcrypt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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 9593e9b..23f28ca 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 @@ -192,6 +192,22 @@ static ltc_ecc_set_type* create_curve(JNIEnv *env, jobject params) { jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;"); jobject p = (*env)->CallObjectMethod(env, field, get_p); + jmethodID biginteger_valueof = (*env)->GetStaticMethodID(env, biginteger_class, "valueOf", "(J)Ljava/math/BigInteger;"); + jobject three = (*env)->CallStaticObjectMethod(env, biginteger_class, biginteger_valueof, (jlong) 3); + + jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getA", "()Ljava/math/BigInteger;"); + jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a); + + jmethodID biginteger_add = (*env)->GetMethodID(env, biginteger_class, "add", "(Ljava/math/BigInteger;)Ljava/math/BigInteger;"); + jobject a_3 = (*env)->CallObjectMethod(env, a, biginteger_add, three); + + jmethodID biginteger_equals = (*env)->GetMethodID(env, biginteger_class, "equals", "(Ljava/lang/Object;)Z"); + jboolean eq = (*env)->CallBooleanMethod(env, p, biginteger_equals, a_3); + + if (!eq) { + return NULL; + } + jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;"); jobject g = (*env)->CallObjectMethod(env, params, get_g); -- cgit v1.3.1 From 2ecf1379142f580730cfaf7ceaca18aeb7af9b40 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 14 Jun 2024 12:44:47 +0200 Subject: Allow malformed sigs in nonce recovery. --- .../main/java/cz/crcs/ectester/common/util/ECUtil.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java index 54c5131..907d75f 100644 --- a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java +++ b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java @@ -3,6 +3,9 @@ package cz.crcs.ectester.common.util; import cz.crcs.ectester.common.ec.*; import cz.crcs.ectester.data.EC_Store; import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.signers.PlainDSAEncoding; @@ -371,14 +374,18 @@ public class ECUtil { } // Parse signature - BigInteger[] sigPair; + BigInteger r; + BigInteger s; if (sigType.contains("CVC") || sigType.contains("PLAIN")) { - sigPair = PlainDSAEncoding.INSTANCE.decode(n, signature); + BigInteger[] sigPair = PlainDSAEncoding.INSTANCE.decode(n, signature); + r = sigPair[0]; + s = sigPair[1]; } else { - sigPair = StandardDSAEncoding.INSTANCE.decode(n, signature); + ASN1Sequence seq = (ASN1Sequence)ASN1Primitive.fromByteArray(signature); + r = ((ASN1Integer)seq.getObjectAt(0)).getValue(); + s = ((ASN1Integer)seq.getObjectAt(1)).getValue(); } - BigInteger r = sigPair[0]; - BigInteger s = sigPair[1]; + BigInteger rd = privkey.multiply(r).mod(n); BigInteger hrd = hashInt.add(rd).mod(n); -- cgit v1.3.1 From 99d463bd5f34ada3f6dcd92073960590b68afbb3 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 14 Jun 2024 14:19:26 +0200 Subject: More detailed signature format tests. --- .../java/cz/crcs/ectester/common/util/ECUtil.java | 39 ++++- .../resources/cz/crcs/ectester/data/schema.xsd | 1 + .../cz/crcs/ectester/data/wrong/results.xml | 163 +++++++++++++++++---- .../test/suites/StandaloneSignatureSuite.java | 2 +- 4 files changed, 170 insertions(+), 35 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java index 907d75f..e7f138e 100644 --- a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java +++ b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java @@ -349,6 +349,39 @@ public class ECUtil { return new KeyPair(pubkey, privkey); } + /** + * Validate DER or PLAIN signature format. + * + * @throws IllegalArgumentException in case of invalid format. + * @param signature + * @param params + * @param hashAlgo + * @param sigType + */ + public static void validateSignatureFormat(byte[] signature, ECParameterSpec params, String hashAlgo, String sigType) { + BigInteger n = params.getOrder(); + try { + if (sigType.contains("CVC") || sigType.contains("PLAIN")) { + PlainDSAEncoding.INSTANCE.decode(n, signature); + } else { + StandardDSAEncoding.INSTANCE.decode(n, signature); + } + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + /** + * Recover the ECDSA signature nonce. + * + * @param signature + * @param data + * @param privkey + * @param params + * @param hashAlgo + * @param sigType + * @return The nonce. + */ public static BigInteger recoverSignatureNonce(byte[] signature, byte[] data, BigInteger privkey, ECParameterSpec params, String hashAlgo, String sigType) { // We do not know how to reconstruct those nonces so far. // sigType.contains("ECKCDSA") || sigType.contains("ECNR") || sigType.contains("SM2") @@ -381,9 +414,9 @@ public class ECUtil { r = sigPair[0]; s = sigPair[1]; } else { - ASN1Sequence seq = (ASN1Sequence)ASN1Primitive.fromByteArray(signature); - r = ((ASN1Integer)seq.getObjectAt(0)).getValue(); - s = ((ASN1Integer)seq.getObjectAt(1)).getValue(); + ASN1Sequence seq = (ASN1Sequence) ASN1Primitive.fromByteArray(signature); + r = ((ASN1Integer) seq.getObjectAt(0)).getValue(); + s = ((ASN1Integer) seq.getObjectAt(1)).getValue(); } diff --git a/common/src/main/resources/cz/crcs/ectester/data/schema.xsd b/common/src/main/resources/cz/crcs/ectester/data/schema.xsd index 99c9b76..245aa9a 100644 --- a/common/src/main/resources/cz/crcs/ectester/data/schema.xsd +++ b/common/src/main/resources/cz/crcs/ectester/data/schema.xsd @@ -82,6 +82,7 @@ + diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/results.xml b/common/src/main/resources/cz/crcs/ectester/data/wrong/results.xml index e3f0967..af5d6dd 100644 --- a/common/src/main/resources/cz/crcs/ectester/data/wrong/results.xml +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/results.xml @@ -23,8 +23,9 @@ nok/random - SHA1 + * 0x30440220e641671e6415629dc8398e35ae1362cb647f293a92553b1594d57fff58df302c02206baafface035e3758eea0dd9ef734976c70b6dd06f4d81d33f5e28bfb8730624 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -32,8 +33,9 @@ nok/r0 - SHA1 - 0x3044022000000000000000000000000000000000000000000000000000000000000000000220d0837b07fe63d225733391e6808a081fd8aeb1359511feba7ca4f266727f968e + * + 0x30250201000220675e2eb20e1f1ec11c3016f7675d9a2e7a3c3370efde499ccb91920ab3da4ef3 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -41,8 +43,9 @@ nok/s0 - SHA1 - 0x304402206bea66d439da6b0b4a0e45b51e76d53336f27f7aa8e35f2008b77a8e021eff0a02200000000000000000000000000000000000000000000000000000000000000000 + * + 0x302502206bea66d439da6b0b4a0e45b51e76d53336f27f7aa8e35f2008b77a8e021eff0a020100 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -50,8 +53,9 @@ nok/r1 - SHA1 - 0x3044022000000000000000000000000000000000000000000000000000000000000000010220e660f19ddc20a30adda6ca175577b492e238ef8734b904a31045d453825974d4 + * + 0x302502010102203494a201a1a539189253c5eab77d1cb99ce1b154c642acc85a956cf2eec2bb3f + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -59,8 +63,9 @@ nok/s1 - SHA1 - 0x30440220d30ab3301d7132edbead77c0d622bbb7be8626c9ac5ee6c536281e6c18e79ab002200000000000000000000000000000000000000000000000000000000000000001 + * + 0x302502201ee448a2ce4695ac5b71d89553e3dd9688f33041f64aa9aed49c269f6f943c25020101 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -68,8 +73,9 @@ nok/r0s0 - SHA1 - 0x30440220000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000 + * + 0x3006020100020100 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -77,8 +83,9 @@ nok/r0s1 - SHA1 - 0x30440220000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000001 + * + 0x3006020100020101 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -86,8 +93,9 @@ nok/r1s0 - SHA1 - 0x30440220000000000000000000000000000000000000000000000000000000000000000102200000000000000000000000000000000000000000000000000000000000000000 + * + 0x3006020101020100 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -95,35 +103,119 @@ nok/r1s1 - SHA1 - 0x30440220000000000000000000000000000000000000000000000000000000000000000102200000000000000000000000000000000000000000000000000000000000000001 + * + 0x3006020101020101 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub Well-formed invalid signature with r = 1 and s = 1. + + nok/r0_padded + * + 0x3044022000000000000000000000000000000000000000000000000000000000000000000220675e2eb20e1f1ec11c3016f7675d9a2e7a3c3370efde499ccb91920ab3da4ef3 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Malformed (zero-padded) invalid signature with r = 0. + + + nok/s0_padded + * + 0x304402206bea66d439da6b0b4a0e45b51e76d53336f27f7aa8e35f2008b77a8e021eff0a02200000000000000000000000000000000000000000000000000000000000000000 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Malformed (zero-padded) invalid signature with s = 0. + + + nok/r1_padded + * + 0x30440220000000000000000000000000000000000000000000000000000000000000000102203494a201a1a539189253c5eab77d1cb99ce1b154c642acc85a956cf2eec2bb3f + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Malformed (zero-padded) invalid signature with r = 1. + + + nok/s1_padded + * + 0x304402201ee448a2ce4695ac5b71d89553e3dd9688f33041f64aa9aed49c269f6f943c2502200000000000000000000000000000000000000000000000000000000000000001 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Malformed (zero-padded) invalid signature with s = 1. + + + nok/r0s0_padded + * + 0x30440220000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Malformed (zero-padded) invalid signature with r = 0 and s = 0. + + + nok/r0s1_padded + * + 0x30440220000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000001 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Malformed (zero-padded) invalid signature with r = 0 and s = 1. + + + nok/r1s0_padded + * + 0x30440220000000000000000000000000000000000000000000000000000000000000000102200000000000000000000000000000000000000000000000000000000000000000 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Malformed (zero-padded) invalid signature with r = 1 and s = 0. + + + nok/r1s1_padded + * + 0x30440220000000000000000000000000000000000000000000000000000000000000000102200000000000000000000000000000000000000000000000000000000000000001 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Malformed (zero-padded) invalid signature with r = 1 and s = 1. + nok/sp - SHA1 + * 0x30440220fc48281b60b73752f3e20c25e8a06b335122d5890db28d2969d3145fcd384e7b0220ffffffff00000001000000000000000000000000ffffffffffffffffffffffff + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub - Well-formed invalid signature s = p. + Malformed (zero-padded) invalid signature s = p. nok/s2p - SHA1 + * 0x30450220feba982489753a51a69fd582673d2e62b6b07cc6374237c1424f1e469cb00a98022101fffffffe00000002000000000000000000000001fffffffffffffffffffffffe + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub - Well-formed invalid signature with s = 2 * p. + Malformed (zero-padded) invalid signature with s = 2 * p. nok/length_overflow16 - SHA1 + * 0x3083ff000002203988322ab9f52c7f11d5d1aa92a2ac0b00275bcad8e934682257323fda672482022052231597382268e8f3b82b99e386ebb7c7db1a8b4a8bdacd496190314e4c5bad + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -131,8 +223,9 @@ nok/length_overflow32 - SHA1 + * 0x3085ff0000000002203988322ab9f52c7f11d5d1aa92a2ac0b00275bcad8e934682257323fda672482022052231597382268e8f3b82b99e386ebb7c7db1a8b4a8bdacd496190314e4c5bad + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -140,8 +233,9 @@ nok/length_overflow64 - SHA1 + * 0x3089ff000000000000000002203988322ab9f52c7f11d5d1aa92a2ac0b00275bcad8e934682257323fda672482022052231597382268e8f3b82b99e386ebb7c7db1a8b4a8bdacd496190314e4c5bad + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -149,8 +243,9 @@ nok/length_indefinite - SHA1 + * 0x308002203988322ab9f52c7f11d5d1aa92a2ac0b00275bcad8e934682257323fda672482022052231597382268e8f3b82b99e386ebb7c7db1a8b4a8bdacd496190314e4c5bad + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -158,8 +253,9 @@ nok/long - SHA1 + * 0x30420220e641671e6415629dc8398e35ae1362cb647f293a92553b1594d57fff58df302c02206baafface035e3758eea0dd9ef734976c70b6dd06f4d81d33f5e28bfb8730624 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -167,8 +263,9 @@ nok/short - SHA1 + * 0x30460220e641671e6415629dc8398e35ae1362cb647f293a92553b1594d57fff58df302c02206baafface035e3758eea0dd9ef734976c70b6dd06f4d81d33f5e28bfb8730624 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -176,8 +273,9 @@ nok/long_r - SHA1 + * 0x3044021ee641671e6415629dc8398e35ae1362cb647f293a92553b1594d57fff58df302c02206baafface035e3758eea0dd9ef734976c70b6dd06f4d81d33f5e28bfb8730624 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -185,8 +283,9 @@ nok/long_s - SHA1 + * 0x30440220e641671e6415629dc8398e35ae1362cb647f293a92553b1594d57fff58df302c021e6baafface035e3758eea0dd9ef734976c70b6dd06f4d81d33f5e28bfb8730624 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -194,8 +293,9 @@ nok/short_r - SHA1 + * 0x30440222e641671e6415629dc8398e35ae1362cb647f293a92553b1594d57fff58df302c02206baafface035e3758eea0dd9ef734976c70b6dd06f4d81d33f5e28bfb8730624 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub @@ -203,8 +303,9 @@ nok/short_s - SHA1 + * 0x30440220e641671e6415629dc8398e35ae1362cb647f293a92553b1594d57fff58df302c02226baafface035e3758eea0dd9ef734976c70b6dd06f4d81d33f5e28bfb8730624 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub 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 bafaa90..8e5e452 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 @@ -73,7 +73,7 @@ public class StandaloneSignatureSuite extends StandaloneTestSuite { } private void ecdsaTest(EC_SigResult sig, SignatureIdent sigIdent, Result.ExpectedValue expected, byte[] defaultData) throws NoSuchAlgorithmException { - if (!sig.getSig().equals(sigIdent.getHashAlgo())) { + if (!sig.getSig().equals(sigIdent.getHashAlgo()) && !sig.getSig().equals("*")) { doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "ECDSA test of " + sig.getId() + " not applicable.")); return; } -- cgit v1.3.1 From aa0406801665327087968e9e19c4140b6471970e Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 14 Jun 2024 14:29:27 +0200 Subject: Only output "Running logs" when in console. --- .../cz/crcs/ectester/common/output/BaseTextTestWriter.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java index 4670f95..1c7e4d4 100644 --- a/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java +++ b/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java @@ -115,19 +115,19 @@ public abstract class BaseTextTestWriter implements TestWriter { @Override public void beginTest(Test t) { - if (t instanceof CompoundTest) { - CompoundTest test = (CompoundTest) t; - } else { - SimpleTest test = (SimpleTest) t; + if (System.console() != null) { + output.print("Running ▶ " + t.getDescription()); + output.flush(); } - output.print("Running ▶ " + t.getDescription()); - output.flush(); } @Override public void endTest(Test t) { - output.print("\33[2K\r"); + if (System.console() != null) { + output.print("\33[2K\r"); + output.flush(); + } } @Override -- cgit v1.3.1 From b2e85d46c029965f76e5f93b11e33cf782386f33 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 14 Jun 2024 14:33:15 +0200 Subject: Fix points on composite order curves. Fixes #27. --- .../main/resources/cz/crcs/ectester/data/cofactor/cofactor128p65535.csv | 2 +- common/src/main/resources/cz/crcs/ectester/data/cofactor/keys.xml | 2 +- .../main/resources/cz/crcs/ectester/data/composite/composite192_pq2.csv | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/main/resources/cz/crcs/ectester/data/cofactor/cofactor128p65535.csv b/common/src/main/resources/cz/crcs/ectester/data/cofactor/cofactor128p65535.csv index 54da6cc..fb16cdb 100644 --- a/common/src/main/resources/cz/crcs/ectester/data/cofactor/cofactor128p65535.csv +++ b/common/src/main/resources/cz/crcs/ectester/data/cofactor/cofactor128p65535.csv @@ -1 +1 @@ -0xdd94e89ef3fba74afc2a67cb91546a93,0x6cf4828ab4960df2b9fcab3990e3959a,0x80a5c32206c83f769c5ed3e4f5b2ea4e,0xd7a4bb4b7e9ad9e81895caeaeac8b739,0x45ebc51cf353974b02b36b9912de041b,0x0000dd95c634ba30617af48fd4eb321b,0xffff \ No newline at end of file +0xdd94e89ef3fba74afc2a67cb91546a93,0x6cf4828ab4960df2b9fcab3990e3959a,0x80a5c32206c83f769c5ed3e4f5b2ea4e,0x91e251594dab368b04d7dd6d9b99fdef,0xa7da97b3ba62ac554f7202d4f0348133,0x0000dd95c634ba30617af48fd4eb321b,0xffff \ No newline at end of file diff --git a/common/src/main/resources/cz/crcs/ectester/data/cofactor/keys.xml b/common/src/main/resources/cz/crcs/ectester/data/cofactor/keys.xml index d6058f0..1b5ec4b 100644 --- a/common/src/main/resources/cz/crcs/ectester/data/cofactor/keys.xml +++ b/common/src/main/resources/cz/crcs/ectester/data/cofactor/keys.xml @@ -668,7 +668,7 @@ pq/cofactor192/1 - 0x6366613b66339fa580f390d630ccf9b535437229aa8b61cd,0x1b975fa3848bd68f34f6a08b7cf190bcaeaf9782270e2413 + 0x28f5b96b08f9dbe661472dbf8e5925b944e42ac5fdfdb2da,0x227e8b2a9b07d1cd67211d4b933bf43eefbb7140e5a65dca composite/pq/composite192/1 cofactor order = 0x00000000000000000000035efd8bad55038e6bd22db8b805 diff --git a/common/src/main/resources/cz/crcs/ectester/data/composite/composite192_pq2.csv b/common/src/main/resources/cz/crcs/ectester/data/composite/composite192_pq2.csv index 33fe0f3..c92dcb2 100644 --- a/common/src/main/resources/cz/crcs/ectester/data/composite/composite192_pq2.csv +++ b/common/src/main/resources/cz/crcs/ectester/data/composite/composite192_pq2.csv @@ -1 +1 @@ -0xa261fff62647eebf810a404f0c80a971dd7c7838fdc52b5b,0x87502ebb62d26e1eca06c434f8ef069dfb2c287d6183750c,0x4ad6ce1f16e1bfc3d40f0027d787aeadb53846d69099a883,0x6366613b66339fa580f390d630ccf9b535437229aa8b61cd,0x1b975fa3848bd68f34f6a08b7cf190bcaeaf9782270e2413,0x00000000000000000000035efd8bad55038e6bd22db8b805,0x01 \ No newline at end of file +0xa261fff62647eebf810a404f0c80a971dd7c7838fdc52b5b,0x87502ebb62d26e1eca06c434f8ef069dfb2c287d6183750c,0x4ad6ce1f16e1bfc3d40f0027d787aeadb53846d69099a883,0x16a5b79035a1e561aae737dc7f32f3c03d5f03f73bd405e4,0x3ddad60cc20b136913dcab69a30e5b71e0bf11f859658524,0x00000000000000000000035efd8bad55038e6bd22db8b805,0x01 \ No newline at end of file -- cgit v1.3.1 From e27e478c0a3ecf37b6e83d63986cc8c53d851095 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 14 Jun 2024 14:45:03 +0200 Subject: Check return values in OpenSSL key loads. Fixes #28. --- .../cz/crcs/ectester/standalone/libs/jni/openssl.c | 31 +++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) 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 fc02e9d..7a6070d 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 @@ -455,10 +455,19 @@ EC_KEY *barray_to_pubkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray pub) { jsize pub_len = (*env)->GetArrayLength(env, pub); jbyte *pub_data = (*env)->GetByteArrayElements(env, pub, NULL); EC_POINT *pub_point = EC_POINT_new(curve); - EC_POINT_oct2point(curve, pub_point, (unsigned char *) pub_data, pub_len, NULL); + int retval = EC_POINT_oct2point(curve, pub_point, (unsigned char *) pub_data, pub_len, NULL); (*env)->ReleaseByteArrayElements(env, pub, pub_data, JNI_ABORT); - EC_KEY_set_public_key(result, pub_point); + if (!retval) { + EC_POINT_free(pub_point); + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_POINT_oct2point."); + return NULL; + } + retval = EC_KEY_set_public_key(result, pub_point); EC_POINT_free(pub_point); + if (!retval) { + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_KEY_set_public_key."); + return NULL; + } return result; } @@ -469,8 +478,12 @@ EC_KEY *barray_to_privkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray priv) jbyte *priv_data = (*env)->GetByteArrayElements(env, priv, NULL); BIGNUM *s = BN_bin2bn((unsigned char *) priv_data, priv_len, NULL); (*env)->ReleaseByteArrayElements(env, priv, priv_data, JNI_ABORT); - EC_KEY_set_private_key(result, s); + int retval = EC_KEY_set_private_key(result, s); BN_free(s); + if (!retval) { + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_KEY_set_private_key."); + return NULL; + } return result; } @@ -482,7 +495,13 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } EC_KEY *pub = barray_to_pubkey(env, curve, pubkey); + if (!pub) { + return NULL; + } EC_KEY *priv = barray_to_privkey(env, curve, privkey); + if (!priv) { + return NULL; + } int field_size = EC_GROUP_get_degree(curve); size_t secret_len = (field_size + 7)/8; @@ -526,6 +545,9 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig } EC_KEY *priv = barray_to_privkey(env, curve, privkey); + if (!priv) { + return NULL; + } jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); @@ -566,6 +588,9 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } EC_KEY *pub = barray_to_pubkey(env, curve, pubkey); + if (!pub) { + return JNI_FALSE; + } jsize sig_len = (*env)->GetArrayLength(env, signature); jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL); -- cgit v1.3.1 From 6c333be59a328dcca776acfbd73f3bd332b8563d Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 15 Jun 2024 12:07:01 +0200 Subject: Cleaner output of compound tests. --- .../ectester/common/output/BaseTextTestWriter.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java index 1c7e4d4..538539b 100644 --- a/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java +++ b/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java @@ -51,11 +51,13 @@ public abstract class BaseTextTestWriter implements TestWriter { private String testString(Test t, String prefix, int index) { boolean compound = t instanceof CompoundTest; + boolean cont = compound ? ((CompoundTest) t).getStartedTests().length > 0 : false; + boolean root = prefix.equals(""); Result result = t.getResult(); String line = ""; - if (prefix.equals("")) { + if (root) { char[] charLine = new char[BASE_WIDTH + 24]; new String(new char[BASE_WIDTH + 24]).replace("\0", "━").getChars(0, charLine.length - 1, charLine, 0); charLine[0] = '■'; @@ -68,10 +70,20 @@ public abstract class BaseTextTestWriter implements TestWriter { StringBuilder out = new StringBuilder(); out.append(t.ok() ? Colors.ok(" OK ") : Colors.error("NOK ")); - out.append(compound ? (prefix.equals("") ? "╋ " : "┳ ") : "━ "); + String marker; + if (compound) { + if (root) { + marker = cont ? "╋" : "┻"; + } else { + marker = cont ? "┳" : "━"; + } + } else { + marker = "━"; + } + out.append(marker + " "); int width = BASE_WIDTH - (prefix.length() + 6); String widthSpec = "%-" + width + "s"; - String desc = ((prefix.equals("")) ? "(" + index + ") " : "") + t.getDescription(); + String desc = ((root) ? "(" + index + ") " : "") + t.getDescription(); out.append(String.format(widthSpec, desc)); out.append(" ┃ "); Colors.Foreground valueColor; -- cgit v1.3.1 From d4c6426df7d1d66c7e2a2f1000d252edfe51c43a Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 15 Jun 2024 12:07:23 +0200 Subject: Error codes in OpenSSL shim. --- .../src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 7a6070d..59eb0db 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 @@ -519,7 +519,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } SIG_CATCH_HANDLE(env); if (err <= 0) { - throw_new(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key."); + throw_new_var(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key (%i).", err); EC_KEY_free(pub); EC_KEY_free(priv); EC_GROUP_free(curve); (*env)->ReleaseByteArrayElements(env, result, result_data, JNI_ABORT); return NULL; @@ -611,7 +611,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); if (result < 0) { - throw_new(env, "java/security/GeneralSecurityException", "Error verifying, ECDSA_do_verify."); + throw_new_var(env, "java/security/GeneralSecurityException", "Error verifying, ECDSA_do_verify (%i).", result); EC_KEY_free(pub); EC_GROUP_free(curve); ECDSA_SIG_free(sig_obj); return JNI_FALSE; } -- cgit v1.3.1 From 9b51ac854de9d9fbf3b884d1cb65f80927cbd6be Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 15 Jun 2024 12:07:33 +0200 Subject: More signature tests. --- .../cz/crcs/ectester/data/wrong/results.xml | 48 ++++++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/common/src/main/resources/cz/crcs/ectester/data/wrong/results.xml b/common/src/main/resources/cz/crcs/ectester/data/wrong/results.xml index af5d6dd..18302b1 100644 --- a/common/src/main/resources/cz/crcs/ectester/data/wrong/results.xml +++ b/common/src/main/resources/cz/crcs/ectester/data/wrong/results.xml @@ -11,6 +11,16 @@ wrong/default_pub A correct signature by the default key. + + nok/malleable/s+n + SHA1 + 0x304502203988322ab9f52c7f11d5d1aa92a2ac0b00275bcad8e934682257323fda67248202210152231596382268e9f3b82b99e386ebb784c21538f1a379523d1b5af44aaf80fe + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + A correct signature modified by adding n to s. + nok/negated SHA1 @@ -194,22 +204,52 @@ nok/sp * - 0x30440220fc48281b60b73752f3e20c25e8a06b335122d5890db28d2969d3145fcd384e7b0220ffffffff00000001000000000000000000000000ffffffffffffffffffffffff + 0x304502207c48281b60b73752f3e20c25e8a06b335122d5890db28d2969d3145fcd384e7b022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub - Malformed (zero-padded) invalid signature s = p. + Well-formed invalid signature s = p. nok/s2p * - 0x30450220feba982489753a51a69fd582673d2e62b6b07cc6374237c1424f1e469cb00a98022101fffffffe00000002000000000000000000000001fffffffffffffffffffffffe + 0x304502207eba982489753a51a69fd582673d2e62b6b07cc6374237c1424f1e469cb00a98022101fffffffe00000002000000000000000000000001fffffffffffffffffffffffe + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Well-formed invalid signature with s = 2 * p. + + + nok/sn + * + 0x304502207c48281b60b73752f3e20c25e8a06b335122d5890db28d2969d3145fcd384e7b022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Well-formed invalid signature s = n. + + + nok/rnsn + * + 0x3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 + 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB + secg/secp256r1 + wrong/default_priv + wrong/default_pub + Well-formed invalid signature r = n and s = n. + + + nok/s2n + * + 0x304502207eba982489753a51a69fd582673d2e62b6b07cc6374237c1424f1e469cb00a98022101fffffffe00000002000000000000000000000001fffffffffffffffffffffffe 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB secg/secp256r1 wrong/default_priv wrong/default_pub - Malformed (zero-padded) invalid signature with s = 2 * p. + Well-formed invalid signature with s = 2 * n. nok/length_overflow16 -- cgit v1.3.1 From 9be29890dc246cac61649052c8501adbb7dfe3d2 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 19 Jun 2024 10:37:52 +0200 Subject: Add pubkey checks to LibreSSL and BoringSSL. Fixes #28. --- .../crcs/ectester/standalone/libs/jni/boringssl.c | 58 +++++++++++++++++----- .../crcs/ectester/standalone/libs/jni/libressl.c | 49 +++++++++++++++--- 2 files changed, 86 insertions(+), 21 deletions(-) diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/boringssl.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/boringssl.c index 6878549..919cc79 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/boringssl.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/boringssl.c @@ -397,11 +397,20 @@ EC_KEY *barray_to_pubkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray pub) { jsize pub_len = (*env)->GetArrayLength(env, pub); jbyte *pub_data = (*env)->GetByteArrayElements(env, pub, NULL); EC_POINT *pub_point = EC_POINT_new(curve); - EC_POINT_oct2point(curve, pub_point, (unsigned char *) pub_data, pub_len, NULL); - (*env)->ReleaseByteArrayElements(env, pub, pub_data, JNI_ABORT); - EC_KEY_set_public_key(result, pub_point); - EC_POINT_free(pub_point); - return result; + int retval = EC_POINT_oct2point(curve, pub_point, (unsigned char *) pub_data, pub_len, NULL); + (*env)->ReleaseByteArrayElements(env, pub, pub_data, JNI_ABORT); + if (!retval) { + EC_POINT_free(pub_point); + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_POINT_oct2point."); + return NULL; + } + retval = EC_KEY_set_public_key(result, pub_point); + EC_POINT_free(pub_point); + if (!retval) { + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_KEY_set_public_key."); + return NULL; + } + return result; } EC_KEY *barray_to_privkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray priv) { @@ -411,27 +420,38 @@ EC_KEY *barray_to_privkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray priv) jbyte *priv_data = (*env)->GetByteArrayElements(env, priv, NULL); BIGNUM *s = BN_bin2bn((unsigned char *) priv_data, priv_len, NULL); (*env)->ReleaseByteArrayElements(env, priv, priv_data, JNI_ABORT); - EC_KEY_set_private_key(result, s); + int retval = EC_KEY_set_private_key(result, s); BN_free(s); + if (!retval) { + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_KEY_set_private_key."); + return NULL; + } return result; } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Boringssl_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { + jbyteArray result = NULL; EC_GROUP *curve = create_curve(env, params); if (!curve) { throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); - return NULL; + goto free_curve; } EC_KEY *pub = barray_to_pubkey(env, curve, pubkey); + if (!pub) { + goto free_pub; + } EC_KEY *priv = barray_to_privkey(env, curve, privkey); + if (!priv) { + goto free_priv; + } int field_size = EC_GROUP_get_degree(curve); size_t secret_len = (field_size + 7)/8; //TODO: Do more KeyAgreements here, but will have to do the hash-fun manually, // probably using the ECDH_KDF_X9_62 by wrapping it and dynamically choosing the EVP_MD. from the type string. - jbyteArray result = (*env)->NewByteArray(env, secret_len); + result = (*env)->NewByteArray(env, secret_len); jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); int err = 0; @@ -449,8 +469,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } (*env)->ReleaseByteArrayElements(env, result, result_data, 0); - EC_KEY_free(pub); +free_priv: EC_KEY_free(priv); +free_pub: + EC_KEY_free(pub); +free_curve: EC_GROUP_free(curve); return result; } @@ -461,13 +484,17 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgr } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Boringssl_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { + jbyteArray result = NULL; EC_GROUP *curve = create_curve(env, params); if (!curve) { throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); - return NULL; + goto free_curve; } EC_KEY *priv = barray_to_privkey(env, curve, privkey); + if (!priv) { + goto free_priv; + } jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); @@ -483,19 +510,20 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); if (!signature) { throw_new(env, "java/security/GeneralSecurityException", "Error signing, ECDSA_do_sign."); - EC_KEY_free(priv); EC_GROUP_free(curve); - return NULL; + goto free_priv; } jsize sig_len = i2d_ECDSA_SIG(signature, NULL); - jbyteArray result = (*env)->NewByteArray(env, sig_len); + result = (*env)->NewByteArray(env, sig_len); jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); jbyte *result_data_ptr = result_data; i2d_ECDSA_SIG(signature, (unsigned char **)&result_data_ptr); (*env)->ReleaseByteArrayElements(env, result, result_data, 0); ECDSA_SIG_free(signature); +free_priv: EC_KEY_free(priv); +free_curve: EC_GROUP_free(curve); return result; } @@ -508,6 +536,10 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } EC_KEY *pub = barray_to_pubkey(env, curve, pubkey); + if (!pub) { + EC_GROUP_free(curve); + return JNI_FALSE; + } jsize sig_len = (*env)->GetArrayLength(env, signature); jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL); diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/libressl.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/libressl.c index 7d50836..d329f45 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/libressl.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/libressl.c @@ -420,10 +420,19 @@ EC_KEY *barray_to_pubkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray pub) { jsize pub_len = (*env)->GetArrayLength(env, pub); jbyte *pub_data = (*env)->GetByteArrayElements(env, pub, NULL); EC_POINT *pub_point = EC_POINT_new(curve); - EC_POINT_oct2point(curve, pub_point, (unsigned char *) pub_data, pub_len, NULL); + int retval = EC_POINT_oct2point(curve, pub_point, (unsigned char *) pub_data, pub_len, NULL); (*env)->ReleaseByteArrayElements(env, pub, pub_data, JNI_ABORT); - EC_KEY_set_public_key(result, pub_point); + if (!retval) { + EC_POINT_free(pub_point); + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_POINT_oct2point."); + return NULL; + } + retval = EC_KEY_set_public_key(result, pub_point); EC_POINT_free(pub_point); + if (!retval) { + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_KEY_set_public_key."); + return NULL; + } return result; } @@ -434,27 +443,38 @@ EC_KEY *barray_to_privkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray priv) jbyte *priv_data = (*env)->GetByteArrayElements(env, priv, NULL); BIGNUM *s = BN_bin2bn((unsigned char *) priv_data, priv_len, NULL); (*env)->ReleaseByteArrayElements(env, priv, priv_data, JNI_ABORT); - EC_KEY_set_private_key(result, s); + int retval = EC_KEY_set_private_key(result, s); BN_free(s); + if (!retval) { + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, EC_KEY_set_private_key."); + return NULL; + } return result; } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Libressl_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { + jbyteArray result = NULL; EC_GROUP *curve = create_curve(env, params); if (!curve) { throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); - return NULL; + goto free_curve; } EC_KEY *pub = barray_to_pubkey(env, curve, pubkey); + if (!pub) { + goto free_pub; + } EC_KEY *priv = barray_to_privkey(env, curve, privkey); + if (!priv) { + goto free_priv; + } int field_size = EC_GROUP_get_degree(curve); size_t secret_len = (field_size + 7)/8; //TODO: Do more KeyAgreements here, but will have to do the hash-fun manually, // probably using the ECDH_KDF_X9_62 by wrapping it and dynamically choosing the EVP_MD. from the type string. - jbyteArray result = (*env)->NewByteArray(env, secret_len); + result = (*env)->NewByteArray(env, secret_len); jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); int err; @@ -472,8 +492,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } (*env)->ReleaseByteArrayElements(env, result, result_data, 0); - EC_KEY_free(pub); +free_priv: EC_KEY_free(priv); +free_pub: + EC_KEY_free(pub); +free_curve: EC_GROUP_free(curve); return result; } @@ -484,13 +507,17 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgr } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Libressl_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { + jbyteArray result = NULL; EC_GROUP *curve = create_curve(env, params); if (!curve) { throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); - return NULL; + goto free_curve; } EC_KEY *priv = barray_to_privkey(env, curve, privkey); + if (!priv) { + goto free_priv; + } jsize data_size = (*env)->GetArrayLength(env, data); jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); @@ -511,14 +538,16 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig } jsize sig_len = i2d_ECDSA_SIG(signature, NULL); - jbyteArray result = (*env)->NewByteArray(env, sig_len); + result = (*env)->NewByteArray(env, sig_len); jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); jbyte *result_data_ptr = result_data; i2d_ECDSA_SIG(signature, (unsigned char **)&result_data_ptr); (*env)->ReleaseByteArrayElements(env, result, result_data, 0); ECDSA_SIG_free(signature); +free_priv: EC_KEY_free(priv); +free_curve: EC_GROUP_free(curve); return result; } @@ -531,6 +560,10 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } EC_KEY *pub = barray_to_pubkey(env, curve, pubkey); + if (!pub) { + EC_GROUP_free(curve); + return JNI_FALSE; + } jsize sig_len = (*env)->GetArrayLength(env, signature); jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL); -- cgit v1.3.1 From b7d077792a282b27875218ef808de067e4953150 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 19 Jun 2024 11:07:32 +0200 Subject: Add point validation to Nettle. --- .../resources/cz/crcs/ectester/standalone/libs/jni/nettle.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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 24ba699..e7ec00e 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 @@ -225,7 +225,10 @@ int barray_to_pubkey(JNIEnv *env, struct ecc_point* pubKey , jbyteArray pub) { mpz_import(x, pointLength, 1, sizeof(unsigned char), 0, 0, pub_data+1); mpz_import(y, pointLength, 1, sizeof(unsigned char), 0, 0, pub_data+1+pointLength); (*env)->ReleaseByteArrayElements(env, pub, pub_data, JNI_ABORT); - ecc_point_set(pubKey, x, y); + if (ecc_point_set(pubKey, x, y) == 0) { + throw_new(env, "java/security/GeneralSecurityException", "Error loading key, ecc_point_set."); + return 0; + } return pointLength; } @@ -267,7 +270,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey struct ecc_point eccPubPoint; ecc_point_init(&eccPubPoint, curve); - barray_to_pubkey(env, &eccPubPoint, pubkey); + int publen = barray_to_pubkey(env, &eccPubPoint, pubkey); + if (publen == 0) { + ecc_scalar_clear(&privScalar); + ecc_point_clear(&eccPubPoint); + return NULL; + } struct ecc_point resultPoint; ecc_point_init(&resultPoint, curve); -- cgit v1.3.1 From 5fee2ecff3c6eee47ca0138bc23603f4c7741c30 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 19 Jun 2024 11:19:42 +0200 Subject: Reformat. --- .../test/suites/StandaloneCofactorSuite.java | 6 ++-- .../test/suites/StandaloneCompositeSuite.java | 40 +++++++++++----------- .../test/suites/StandaloneDegenerateSuite.java | 8 ++--- .../test/suites/StandaloneEdgeCasesSuite.java | 4 +-- .../test/suites/StandaloneInvalidSuite.java | 8 ++--- .../test/suites/StandalonePerformanceSuite.java | 12 +++---- .../test/suites/StandaloneTestVectorSuite.java | 2 +- .../test/suites/StandaloneTwistSuite.java | 8 ++--- .../test/suites/StandaloneWrongSuite.java | 36 +++++++++---------- 9 files changed, 62 insertions(+), 62 deletions(-) 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 52b0fbf..bb9a509 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 @@ -76,10 +76,10 @@ public class StandaloneCofactorSuite extends StandaloneTestSuite { ECParameterSpec spec = curve.toSpec(); KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); - Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); runTest(generate); KeyPair kp = kgt.getKeyPair(); - if(kp == null) { + if (kp == null) { Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Cofactor test of " + curve.getId() + ".", generateFail)); continue; @@ -101,7 +101,7 @@ public class StandaloneCofactorSuite extends StandaloneTestSuite { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with public points on non-generator subgroup.", specificKaTests.toArray(new Test[0]))); } } - if(allKaTests.isEmpty()) { + if (allKaTests.isEmpty()) { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); } Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[0])); 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 c59d864..839bb40 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 @@ -85,10 +85,10 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite { //Generate KeyPair KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); - Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); runTest(generate); KeyPair kp = kgt.getKeyPair(); - if(kp == null) { + if (kp == null) { Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ".", generateFail)); continue; @@ -104,14 +104,14 @@ 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, ecpriv ,ecpub); + KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub); 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)); } allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with various public points.", specificKaTests.toArray(new Test[0]))); } } - if(allKaTests.isEmpty()) { + if (allKaTests.isEmpty()) { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); } Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[0])); @@ -153,7 +153,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite { } private void testGroup(List curves, KeyPairGenerator kpg, String testName, Result.ExpectedValue dhValue) throws Exception { - for (EC_Curve curve : curves) { + for (EC_Curve curve : curves) { String description; if (testName == null) { description = curve.getDesc() + " test of " + curve.getId() + "."; @@ -162,19 +162,19 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite { } //generate KeyPair - KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, curve.toSpec()); - Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); - runTest(generate); - KeyPair kp = kgt.getKeyPair(); - if(kp == null) { - Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + - ". " + " Other tests will be skipped.", generate); - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, description, generateFail)); - continue; - } - Test generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); - ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); - ECPublicKey ecpub = (ECPublicKey) kp.getPublic(); + KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, curve.toSpec()); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + runTest(generate); + KeyPair kp = kgt.getKeyPair(); + if (kp == null) { + Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + + ". " + " Other tests will be skipped.", generate); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, description, generateFail)); + continue; + } + Test generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); + ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); + ECPublicKey ecpub = (ECPublicKey) kp.getPublic(); //perform KeyAgreement tests List kaTests = new LinkedList<>(); @@ -185,7 +185,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite { kaTests.add(KeyAgreementTest.expectError(testable, dhValue)); } } - if(kaTests.isEmpty()) { + if (kaTests.isEmpty()) { kaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified KeyAgreement types is supported by the library.")); } @@ -198,7 +198,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite { sigTests.add(SignatureTest.expectError(testable, dhValue)); } } - if(sigTests.isEmpty()) { + if (sigTests.isEmpty()) { sigTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified Signature types is supported by the library.")); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDegenerateSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDegenerateSuite.java index 9ab8a39..45000df 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDegenerateSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDegenerateSuite.java @@ -77,17 +77,17 @@ public class StandaloneDegenerateSuite extends StandaloneTestSuite { KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); Test generateSuccess; - Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); runTest(generate); KeyPair kp = kgt.getKeyPair(); - if(kp != null) { + if (kp != null) { generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); } else { //If KeyPair generation fails, try generating it on a default curve instead. Use this key only if it has the same domain parameters as our public key. KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits()); Test generateOnDefaultCurve = KeyGeneratorTest.expectError(kgtOnDefaultCurve, Result.ExpectedValue.ANY); runTest(generateOnDefaultCurve); kp = kgtOnDefaultCurve.getKeyPair(); - if(kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { + if (kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generateOnDefaultCurve); } else { Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); @@ -111,7 +111,7 @@ public class StandaloneDegenerateSuite extends StandaloneTestSuite { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with degenerate public points..", specificKaTests.toArray(new Test[0]))); } } - if(allKaTests.isEmpty()) { + if (allKaTests.isEmpty()) { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); } Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[0])); 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 1900bea..7c46f02 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 @@ -264,10 +264,10 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite { //generate KeyPair KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); - Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); runTest(generate); KeyPair kp = kgt.getKeyPair(); - if(kp == null) { + if (kp == null) { Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + secp160r1.getBits() + "b secp160r1." + " Other tests will be skipped.", generate); doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test private key values near zero, near p and near/larger than the order on" + secp160r1.getId() + ".", generateFail)); diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java index ace8945..391fc34 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java @@ -76,17 +76,17 @@ public class StandaloneInvalidSuite extends StandaloneTestSuite { KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); Test generateSuccess; - Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); runTest(generate); KeyPair kp = kgt.getKeyPair(); - if(kp != null) { + if (kp != null) { generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); } else { //If KeyPair generation fails, try generating it on a default curve instead. Use this key only if it has the same domain parameters as our public key. KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits()); Test generateOnDefaultCurve = KeyGeneratorTest.expectError(kgtOnDefaultCurve, Result.ExpectedValue.ANY); runTest(generateOnDefaultCurve); kp = kgtOnDefaultCurve.getKeyPair(); - if(kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { + if (kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generateOnDefaultCurve); } else { Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); @@ -110,7 +110,7 @@ public class StandaloneInvalidSuite extends StandaloneTestSuite { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with invalid public points.", specificKaTests.toArray(new Test[0]))); } } - if(allKaTests.isEmpty()) { + if (allKaTests.isEmpty()) { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); } Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[0])); 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 e3b6d2e..a1b4d75 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 @@ -73,7 +73,7 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite { KeyGeneratorTestable kgtOther = null; ECParameterSpec spec = null; List kpgTests = new LinkedList<>(); - for(KeyPairGeneratorIdent kpgIdent : kpgIdents) { + for (KeyPairGeneratorIdent kpgIdent : kpgIdents) { KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider()); if (cli.hasOption("test.bits")) { int bits = Integer.parseInt(cli.getOptionValue("test.bits")); @@ -111,7 +111,7 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite { kaTests.add(PerformanceTest.repeat(testable, cfg.selected, kaIdent.getName(), count)); } } - if(kaTests.isEmpty()) { + if (kaTests.isEmpty()) { kaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified KeyAgreement types is supported by the library.")); } doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyAgreement performance tests", kaTests.toArray(new Test[0]))); @@ -121,17 +121,17 @@ 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)); - if(kgtOne.getKeyPair() != null) { + sigTests.add(PerformanceTest.repeat(new SignatureTestable(sig, kgtOne, null), cfg.selected, sigIdent.getName(), count)); + 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)); } } } - if(sigTestsNoVerification.isEmpty() & !sigTests.isEmpty()) { + if (sigTestsNoVerification.isEmpty() & !sigTests.isEmpty()) { sigTestsNoVerification.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Signature tests with no verification require a successfully generated private key.")); } - if(sigTests.isEmpty()) { + if (sigTests.isEmpty()) { sigTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified Signature types is supported by the library.")); sigTestsNoVerification.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified Signature types is supported by the library.")); } 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 1e1889c..111d354 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 @@ -31,7 +31,7 @@ public class StandaloneTestVectorSuite extends StandaloneTestSuite { protected void runTests() throws Exception { Map results = EC_Store.getInstance().getObjects(EC_KAResult.class, "test"); for (EC_KAResult result : results.values()) { - if(!"DH_PLAIN".equals(result.getKA())) { + if (!"DH_PLAIN".equals(result.getKA())) { continue; } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java index f182952..84228e7 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java @@ -76,17 +76,17 @@ public class StandaloneTwistSuite extends StandaloneTestSuite { KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); Test generateSuccess; - Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); runTest(generate); KeyPair kp = kgt.getKeyPair(); - if(kp != null) { + if (kp != null) { generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); } else { //If KeyPair generation fails, try generating it on a default curve instead. Use this key only if it has the same domain parameters as our public key. KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits()); Test generateOnDefaultCurve = KeyGeneratorTest.expectError(kgtOnDefaultCurve, Result.ExpectedValue.ANY); runTest(generateOnDefaultCurve); kp = kgtOnDefaultCurve.getKeyPair(); - if(kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { + if (kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generateOnDefaultCurve); } else { Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); @@ -110,7 +110,7 @@ public class StandaloneTwistSuite extends StandaloneTestSuite { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with public points on twist.", specificKaTests.toArray(new Test[0]))); } } - if(allKaTests.isEmpty()) { + if (allKaTests.isEmpty()) { allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); } Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[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 a457a33..1aae9d5 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 @@ -103,7 +103,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { /* Just do the default run on the wrong curves. * These should generally fail, the curves aren't curves. */ - if(!skip) { + if (!skip) { Map wrongCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "wrong"); for (Map.Entry e : wrongCurves.entrySet()) { @@ -151,11 +151,11 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { short bits = curve.getBits(); final byte[] originalp = curve.getParam(EC_Consts.PARAMETER_FP)[0]; - curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{ ByteUtil.hexToBytes("0")}); - Test prime0 = ecdhTest(toCustomSpec(curve),"ECDH with p = 0."); + curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{ByteUtil.hexToBytes("0")}); + Test prime0 = ecdhTest(toCustomSpec(curve), "ECDH with p = 0."); - curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{ ByteUtil.hexToBytes("1")}); - Test prime1 = ecdhTest(toCustomSpec(curve),"ECDH with p = 1."); + curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{ByteUtil.hexToBytes("1")}); + Test prime1 = ecdhTest(toCustomSpec(curve), "ECDH with p = 1."); short keyHalf = (short) (bits / 2); BigInteger prime = new BigInteger(keyHalf, 50, r); @@ -173,23 +173,23 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { Test composite = ecdhTest(toCustomSpec(curve), "ECDH with p = q * s."); - Test wrongPrime = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted prime parameter.", prime0 , prime1, primePower, composite ); + Test wrongPrime = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted prime parameter.", prime0, prime1, primePower, composite); - curve.setParam(EC_Consts.PARAMETER_FP, new byte[][] {originalp}); + curve.setParam(EC_Consts.PARAMETER_FP, new byte[][]{originalp}); final byte[][] originalG = curve.getParam(EC_Consts.PARAMETER_G); byte[] Gx = new BigInteger(curve.getBits(), r).toByteArray(); byte[] Gy = new BigInteger(curve.getBits(), r).toByteArray(); - curve.setParam(EC_Consts.PARAMETER_G, new byte[][] {Gx, Gy}); + curve.setParam(EC_Consts.PARAMETER_G, new byte[][]{Gx, Gy}); Test fullRandomG = ecdhTest(toCustomSpec(curve), "ECDH with G = random data."); final BigInteger originalBigp = new BigInteger(1, originalp); byte[] smallerGx = new BigInteger(curve.getBits(), r).mod(originalBigp).toByteArray(); byte[] smallerGy = new BigInteger(curve.getBits(), r).mod(originalBigp).toByteArray(); - curve.setParam(EC_Consts.PARAMETER_G, new byte[][] {smallerGx, smallerGy}); + curve.setParam(EC_Consts.PARAMETER_G, new byte[][]{smallerGx, smallerGy}); Test randomG = ecdhTest(toCustomSpec(curve), "ECDH with G = random data mod p."); - curve.setParam(EC_Consts.PARAMETER_G, new byte[][] {ByteUtil.hexToBytes("0"), ByteUtil.hexToBytes("0")}); + curve.setParam(EC_Consts.PARAMETER_G, new byte[][]{ByteUtil.hexToBytes("0"), ByteUtil.hexToBytes("0")}); Test zeroG = ecdhTest(toCustomSpec(curve), "ECDH with G = infinity."); Test wrongG = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted G parameter.", fullRandomG, randomG, zeroG); @@ -199,7 +199,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { final BigInteger originalBigR = new BigInteger(1, originalR); List allRTests = new LinkedList<>(); - if(!skip) { + if (!skip) { byte[] RZero = new byte[]{(byte) 0}; curve.setParam(EC_Consts.PARAMETER_R, new byte[][]{RZero}); allRTests.add(ecdhTest(toCustomSpec(curve), "ECDH with R = 0.")); @@ -215,7 +215,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { prevPrimeR = BigInteger.probablePrime(originalBigR.bitLength() - 1, r); } while (prevPrimeR.compareTo(originalBigR) >= 0); byte[] prevRBytes = ECUtil.toByteArray(prevPrimeR, bits); - curve.setParam(EC_Consts.PARAMETER_R, new byte[][] {prevRBytes}); + curve.setParam(EC_Consts.PARAMETER_R, new byte[][]{prevRBytes}); allRTests.add(ecdhTest(toCustomSpec(curve), "ECDH with R = some prime (but [r]G != infinity) smaller than original R.")); BigInteger nextPrimeR = originalBigR.nextProbablePrime(); @@ -225,15 +225,15 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { byte[] nonprimeRBytes = nextRBytes.clone(); nonprimeRBytes[nonprimeRBytes.length - 1] ^= 1; - curve.setParam(EC_Consts.PARAMETER_R, new byte[][] {nonprimeRBytes} ); + curve.setParam(EC_Consts.PARAMETER_R, new byte[][]{nonprimeRBytes}); allRTests.add(ecdhTest(toCustomSpec(curve), "ECDH with R = some composite (but [r]G != infinity).")); Test wrongR = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted R parameter.", allRTests.toArray(new Test[0])); - curve.setParam(EC_Consts.PARAMETER_R, new byte[][] {originalR}); + curve.setParam(EC_Consts.PARAMETER_R, new byte[][]{originalR}); byte[] kRaw = new byte[]{(byte) 0xff}; - curve.setParam(EC_Consts.PARAMETER_K, new byte[][] {kRaw}); + curve.setParam(EC_Consts.PARAMETER_K, new byte[][]{kRaw}); Test bigK = ecdhTest(toCustomSpec(curve), "ECDH with big K."); byte[] kZero = new byte[]{(byte) 0}; @@ -241,7 +241,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { Test zeroK = ecdhTest(toCustomSpec(curve), "ECDH with K = 0."); Test wrongK = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with corrupted K parameter.", bigK, zeroK); - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests of " + bits + "b " + "FP", wrongPrime, wrongG, wrongR , wrongK)); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests of " + bits + "b " + "FP", wrongPrime, wrongG, wrongR, wrongK)); } @@ -284,10 +284,10 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { private Test ecdhTest(ECParameterSpec spec, String desc) throws NoSuchAlgorithmException { //generate KeyPair KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); - Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.FAILURE); + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.FAILURE); runTest(generate); KeyPair kp = kgt.getKeyPair(); - if(kp == null) { + if (kp == null) { return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, generate); } ECPublicKey pub = (ECPublicKey) kp.getPublic(); -- cgit v1.3.1 From c38ef1edaa6e0a1e97cf81274c8b2c24fea63bce Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 19 Jun 2024 12:53:14 +0200 Subject: Fix libgcrypt with secp256k1. --- .../resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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 705a873..0c141dd 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 @@ -181,8 +181,11 @@ static jobject mpi_to_biginteger(JNIEnv *env, gcry_mpi_t mpi) { return NULL; } - jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); jbyteArray bytes = mpi_to_bytearray(env, mpi); + if (!bytes) { + return NULL; + } + jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, bytes); return result; } @@ -245,7 +248,11 @@ static jobject create_ec_param_spec(JNIEnv *env, gcry_sexp_t key) { jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "", "(Ljava/math/BigInteger;)V"); jobject field = (*env)->NewObject(env, fp_field_class, fp_field_init, pi); - jobject ai = mpi_to_biginteger(env, a); + jobject ai = mpi_to_biginteger(env, a); + if (!ai) { + jmethodID biginteger_valueof = (*env)->GetStaticMethodID(env, biginteger_class, "valueOf", "(J)Ljava/math/BigInteger;"); + ai = (*env)->CallStaticObjectMethod(env, biginteger_class, biginteger_valueof, (jlong)0); + } jobject bi = mpi_to_biginteger(env, b); jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); -- cgit v1.3.1 From 57c4f0ea9e428e3634bae389d9f8409a856a15f7 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 19 Jun 2024 14:59:38 +0200 Subject: Fix libgcrypt issues. --- .../standalone/test/base/KeyGeneratorTest.java | 14 ++++++++- .../standalone/test/base/KeyGeneratorTestable.java | 17 ++++++++++- .../test/suites/StandaloneDegenerateSuite.java | 33 +++++++++++++++------- .../test/suites/StandaloneInvalidSuite.java | 33 +++++++++++++++------- .../test/suites/StandaloneTwistSuite.java | 33 +++++++++++++++------- .../cz/crcs/ectester/standalone/libs/jni/gcrypt.c | 30 ++++++-------------- 6 files changed, 106 insertions(+), 54 deletions(-) diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java index 32f82cb..8c49224 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java @@ -4,6 +4,9 @@ import cz.crcs.ectester.common.test.Result; import cz.crcs.ectester.common.test.SimpleTest; import cz.crcs.ectester.common.test.TestCallback; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; + /** * @author Jan Jancar johny@neuromancer.sk */ @@ -38,6 +41,15 @@ public class KeyGeneratorTest extends SimpleTest { @Override public String getDescription() { - return "KeyPairGenerator " + testable.getKpg().getAlgorithm(); + String params = ""; + if (testable.getKeysize() != 0) { + params = String.format("(default %d-bit curve)", testable.getKeysize()); + } else if (testable.getSpec() instanceof ECGenParameterSpec) { + String name = ((ECGenParameterSpec)testable.getSpec()).getName(); + params = String.format("(%s)", name); + } else if (testable.getSpec() instanceof ECParameterSpec) { + params = "(custom curve)"; + } + return "KeyPairGenerator " + testable.getKpg().getAlgorithm() + " on " + params; } } 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 296ec3c..bc44eb8 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,8 @@ package cz.crcs.ectester.standalone.test.base; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; /** @@ -12,7 +14,7 @@ public class KeyGeneratorTestable extends StandaloneTestable new Result(Result.Value.FAILURE, "Default parameters do not match the curve " + curve.getId()), "Default parameters do not match the curve " + curve.getId(), generateOnDefaultCurve); + Test generateFail = CompoundTest.any(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate, generateOnNamedCurve, generateNotEqual); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId() + ".", generateFail)); + continue; + } } } ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java index 391fc34..48dfc37 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java @@ -22,6 +22,7 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; +import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.util.*; @@ -81,17 +82,29 @@ public class StandaloneInvalidSuite extends StandaloneTestSuite { KeyPair kp = kgt.getKeyPair(); if (kp != null) { generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); - } else { //If KeyPair generation fails, try generating it on a default curve instead. Use this key only if it has the same domain parameters as our public key. - KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits()); - Test generateOnDefaultCurve = KeyGeneratorTest.expectError(kgtOnDefaultCurve, Result.ExpectedValue.ANY); - runTest(generateOnDefaultCurve); - kp = kgtOnDefaultCurve.getKeyPair(); - if (kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { - generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generateOnDefaultCurve); + } else { + // If KeyPair generation fails, try generating it on named curve instead. + ECGenParameterSpec namedSpec = new ECGenParameterSpec(curve.getId()); + KeyGeneratorTestable kgtOnNamedCurve = new KeyGeneratorTestable(kpg, namedSpec); + Test generateOnNamedCurve = KeyGeneratorTest.expectError(kgtOnNamedCurve, Result.ExpectedValue.ANY); + runTest(generateOnNamedCurve); + kp = kgtOnNamedCurve.getKeyPair(); + if (kp != null) { + generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair (named curve).", generateOnNamedCurve); } else { - Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId() + ".", generateFail)); - continue; + // If even the named curve generation fails, try generating with the default curve instead. Use this key only if it has the same domain parameters as our public key. + KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits()); + Test generateOnDefaultCurve = KeyGeneratorTest.expectError(kgtOnDefaultCurve, Result.ExpectedValue.ANY); + runTest(generateOnDefaultCurve); + kp = kgtOnDefaultCurve.getKeyPair(); + if (kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { + generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair (default curve).", generateOnDefaultCurve); + } else { + Test generateNotEqual = CompoundTest.function(tests -> new Result(Result.Value.FAILURE, "Default parameters do not match the curve " + curve.getId()), "Default parameters do not match the curve " + curve.getId(), generateOnDefaultCurve); + Test generateFail = CompoundTest.any(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate, generateOnNamedCurve, generateNotEqual); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId() + ".", generateFail)); + continue; + } } } ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java index 84228e7..37adbb2 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java @@ -22,6 +22,7 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; +import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.util.*; @@ -81,17 +82,29 @@ public class StandaloneTwistSuite extends StandaloneTestSuite { KeyPair kp = kgt.getKeyPair(); if (kp != null) { generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); - } else { //If KeyPair generation fails, try generating it on a default curve instead. Use this key only if it has the same domain parameters as our public key. - KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits()); - Test generateOnDefaultCurve = KeyGeneratorTest.expectError(kgtOnDefaultCurve, Result.ExpectedValue.ANY); - runTest(generateOnDefaultCurve); - kp = kgtOnDefaultCurve.getKeyPair(); - if (kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { - generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generateOnDefaultCurve); + } else { + // If KeyPair generation fails, try generating it on named curve instead. + ECGenParameterSpec namedSpec = new ECGenParameterSpec(curve.getId()); + KeyGeneratorTestable kgtOnNamedCurve = new KeyGeneratorTestable(kpg, namedSpec); + Test generateOnNamedCurve = KeyGeneratorTest.expectError(kgtOnNamedCurve, Result.ExpectedValue.ANY); + runTest(generateOnNamedCurve); + kp = kgtOnNamedCurve.getKeyPair(); + if (kp != null) { + generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair (named curve).", generateOnNamedCurve); } else { - Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId() + ".", generateFail)); - continue; + // If even the named curve generation fails, try generating with the default curve instead. Use this key only if it has the same domain parameters as our public key. + KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits()); + Test generateOnDefaultCurve = KeyGeneratorTest.expectError(kgtOnDefaultCurve, Result.ExpectedValue.ANY); + runTest(generateOnDefaultCurve); + kp = kgtOnDefaultCurve.getKeyPair(); + if (kp != null && ECUtil.equalKeyPairParameters((ECPrivateKey) kp.getPrivate(), ECUtil.toPublicKey(keys.get(0)))) { + generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair (default curve).", generateOnDefaultCurve); + } else { + Test generateNotEqual = CompoundTest.function(tests -> new Result(Result.Value.FAILURE, "Default parameters do not match the curve " + curve.getId()), "Default parameters do not match the curve " + curve.getId(), generateOnDefaultCurve); + Test generateFail = CompoundTest.any(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate, generateOnNamedCurve, generateNotEqual); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId() + ".", generateFail)); + continue; + } } } ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); 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 0c141dd..795c30a 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 @@ -200,20 +200,6 @@ static gcry_mpi_t biginteger_to_mpi(JNIEnv *env, jobject bigint) { return bytearray_to_mpi(env, byte_array); } -static jint mpi_to_jint(gcry_mpi_t mpi) { - jint result = 0; - unsigned long nbits = gcry_mpi_get_nbits(mpi); - int max_bits = sizeof(jint) * 8; - for (size_t i = 0; i < nbits && i < max_bits; ++i) { - if (gcry_mpi_test_bit(mpi, nbits - i - 1)) { - result = ((result << 1) | 1); - } else { - result = (result << 1); - } - } - return result; -} - static jobject buff_to_ecpoint(JNIEnv *env, gcry_buffer_t buff) { jint coord_size = (buff.len - 1) / 2; jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); @@ -236,9 +222,10 @@ static jobject buff_to_ecpoint(JNIEnv *env, gcry_buffer_t buff) { static jobject create_ec_param_spec(JNIEnv *env, gcry_sexp_t key) { jobject result = NULL; - gcry_mpi_t p, a, b, n, h; + gcry_mpi_t p, a, b, n; + unsigned int h; gcry_buffer_t g = {0}; - gcry_error_t err = gcry_sexp_extract_param(key, "ecc", "pab&g+nh", &p, &a, &b, &g, &n, &h, NULL); + gcry_error_t err = gcry_sexp_extract_param(key, "ecc", "pab&g+n%uh", &p, &a, &b, &g, &n, &h, NULL); if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { throw_new_var(env, "java/security/GeneralSecurityException", "Error exporting domain parameters. Error: %ui", gcry_err_code(err)); goto end; @@ -261,7 +248,7 @@ static jobject create_ec_param_spec(JNIEnv *env, gcry_sexp_t key) { jobject gen = buff_to_ecpoint(env, g); jobject order = mpi_to_biginteger(env, n); - jint cofactor = mpi_to_jint(h); + jint cofactor = (jint) h; jmethodID ec_parameter_spec_init = (*env)->GetMethodID(env, ec_parameter_spec_class, "", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V"); result = (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, gen, order, cofactor); @@ -272,7 +259,6 @@ end: gcry_mpi_release(b); gcry_free(g.data); gcry_mpi_release(n); - gcry_mpi_release(h); return result; } @@ -479,7 +465,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } SIG_CATCH_HANDLE(env); if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { - throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDH. Error: %ui", gcry_err_code(err)); + throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDH. Error: %u", gcry_err_code(err)); goto end; } @@ -594,7 +580,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig } SIG_CATCH_HANDLE(env); if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { - throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDSA. Error: %ui", gcry_err_code(err)); + throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDSA. Error: %u", gcry_err_code(err)); goto release_init; } @@ -602,7 +588,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig gcry_buffer_t s_buf = {0}; err = gcry_sexp_extract_param(res_sexp, "ecdsa", "&rs", &r_buf, &s_buf, NULL); if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { - throw_new_var(env, "java/security/GeneralSecurityException", "Error extracting ECDSA output. Error: %ui", gcry_err_code(err)); + throw_new_var(env, "java/security/GeneralSecurityException", "Error extracting ECDSA output. Error: %u", gcry_err_code(err)); goto release_res; } result = asn1_der_encode(env, r_buf.data, r_buf.len, s_buf.data, s_buf.len); @@ -654,7 +640,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna if (gcry_err_code(err) != GPG_ERR_NO_ERROR) { if (gcry_err_code(err) != GPG_ERR_BAD_SIGNATURE) { - throw_new(env, "java/security/GeneralSecurityException", "Error verif sig."); + throw_new_var(env, "java/security/GeneralSecurityException", "Error verif sig. Error: %u", gcry_err_code(err)); goto release_init; } } else { -- cgit v1.3.1 From 9c2b3c836bddddd9486d7ed74b5a95af683ff83e Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 21 Jun 2024 14:23:31 +0200 Subject: Always write shims to shim directory, do not check for freshness. --- .../src/main/java/cz/crcs/ectester/common/util/FileUtil.java | 11 +++++++++++ ext/boringssl | 2 +- .../java/cz/crcs/ectester/standalone/ECTesterStandalone.java | 6 +++--- .../cz/crcs/ectester/standalone/libs/NativeECLibrary.java | 4 ++-- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java b/common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java index e6e319b..da682b6 100644 --- a/common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java +++ b/common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java @@ -81,6 +81,17 @@ public class FileUtil { return true; } + public static boolean write(String resourcePath, Path outPath) throws IOException { + URL reqURL = FileUtil.class.getResource(resourcePath); + if (reqURL == null) { + return false; + } + URLConnection reqConn = reqURL.openConnection(); + Files.copy(reqConn.getInputStream(), outPath, StandardCopyOption.REPLACE_EXISTING); + reqConn.getInputStream().close(); + return true; + } + public static Path getLibDir() { return getAppData().resolve("ECTesterStandalone"); } diff --git a/ext/boringssl b/ext/boringssl index 80a243e..67422ed 160000 --- a/ext/boringssl +++ b/ext/boringssl @@ -1 +1 @@ -Subproject commit 80a243e07ef77156af66efa7d22ac35aba44c1b3 +Subproject commit 67422ed4434116daa8898773692165ddd51a6ac2 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 2b9a853..10e95ca 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -103,12 +103,12 @@ public class ECTesterStandalone { reqs.toFile().mkdirs(); if (!System.getProperty("os.name").startsWith("Windows")) { - FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_timing.so", reqs.resolve("lib_timing.so")); + FileUtil.write(LIB_RESOURCE_DIR + "lib_timing.so", reqs.resolve("lib_timing.so")); System.load(reqs.resolve("lib_timing.so").toString()); - FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_csignals.so", reqs.resolve("lib_csignals.so")); + FileUtil.write(LIB_RESOURCE_DIR + "lib_csignals.so", reqs.resolve("lib_csignals.so")); System.load(reqs.resolve("lib_csignals.so").toString()); - FileUtil.writeNewer(LIB_RESOURCE_DIR + "lib_cppsignals.so", reqs.resolve("lib_cppsignals.so")); + FileUtil.write(LIB_RESOURCE_DIR + "lib_cppsignals.so", reqs.resolve("lib_cppsignals.so")); System.load(reqs.resolve("lib_cppsignals.so").toString()); } 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 7f9d96e..c11dbdb 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 @@ -33,7 +33,7 @@ public abstract class NativeECLibrary extends ProviderECLibrary { Path libPath = libDir.resolve(resource + "." + suffix); /* Write the shim. */ - boolean found = FileUtil.writeNewer(ECTesterStandalone.LIB_RESOURCE_DIR + resource + "." + suffix, libPath); + boolean found = FileUtil.write(ECTesterStandalone.LIB_RESOURCE_DIR + resource + "." + suffix, libPath); if (!found) { return false; } @@ -44,7 +44,7 @@ public abstract class NativeECLibrary extends ProviderECLibrary { if (requirement.endsWith(suffix)) { /* The requirement is bundled, write it */ Path reqPath = libReqDir.resolve(requirement); - found = FileUtil.writeNewer(ECTesterStandalone.LIB_RESOURCE_DIR + requirement, reqPath); + found = FileUtil.write(ECTesterStandalone.LIB_RESOURCE_DIR + requirement, reqPath); if (!found) { return false; } -- cgit v1.3.1 From c112d3e49bbbbf33cc70d12d196e109543c19a3c Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 21 Jun 2024 14:36:23 +0200 Subject: Push library initialization deeper and only initialize when necessary. --- .../ectester/standalone/ECTesterStandalone.java | 30 +++++++++++++--------- 1 file changed, 18 insertions(+), 12 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 10e95ca..e6d8188 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -136,16 +136,6 @@ public class ECTesterStandalone { } libs = libObjects.toArray(new ProviderECLibrary[0]); - //TODO: push this further down to only initialize if necessary. - // and only initialize the chosen lib (so give libs a name in Java only) - for (ECLibrary lib : libs) { - try { - lib.initialize(); - } catch (Exception ex) { - System.err.println(ex.getMessage()); - } - } - cfg = new Config(libs); if (!cfg.readOptions(cli)) { return; @@ -302,7 +292,17 @@ public class ECTesterStandalone { */ private void listLibraries() { for (ProviderECLibrary lib : libs) { - if (lib.isInitialized() && (cfg.selected == null || lib == cfg.selected)) { + if (cfg.selected == null || lib == cfg.selected) { + try { + if (!lib.initialize()) { + continue; + } + } catch (Exception ex) { + System.err.println("Error initializing " + lib.fullName()); + System.err.println(ex.getMessage()); + continue; + } + System.out.println("\t- " + Colors.bold(lib.name())); System.out.println(Colors.bold("\t\t- Fullname: ") + lib.getProvider().getName()); System.out.println(Colors.bold("\t\t- Version: ") + lib.getProvider().getVersionStr()); @@ -942,7 +942,7 @@ public class ECTesterStandalone { if (libraryName != null) { List matchedLibs = new LinkedList<>(); for (ProviderECLibrary lib : libs) { - if (lib.isInitialized() && lib.name().toLowerCase().contains(libraryName.toLowerCase())) { + if (lib.name().toLowerCase().contains(libraryName.toLowerCase())) { matchedLibs.add(lib); } } @@ -954,6 +954,12 @@ public class ECTesterStandalone { return false; } else { selected = matchedLibs.get(0); + try { + selected.initialize(); + } catch (Exception ex) { + System.err.println("Error initializing " + selected.fullName()); + System.err.println(ex.getMessage()); + } } } } -- cgit v1.3.1