aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml19
-rw-r--r--README.md122
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/util/Util.java23
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java62
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/output/TextTestWriter.java3
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardCofactorSuite.java11
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardCompositeSuite.java11
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardCompressionSuite.java3
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardDefaultSuite.java2
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardDegenerateSuite.java6
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java8
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardInvalidSuite.java4
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardMiscSuite.java2
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardSignatureSuite.java2
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java74
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardTestVectorSuite.java2
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardTwistSuite.java4
-rw-r--r--reader/src/main/java/cz/crcs/ectester/reader/test/CardWrongSuite.java4
-rw-r--r--reader/src/test/java/cz/crcs/ectester/reader/OutputTests.java13
-rw-r--r--standalone/build.gradle.kts8
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java187
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java12
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java3
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java16
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java12
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java6
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java4
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java4
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java1
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java184
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java80
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java24
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java4
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java11
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java20
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java12
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java8
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java8
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java28
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java4
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java20
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java2
-rw-r--r--standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java10
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile40
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp47
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c316
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c18
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp27
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c6
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c23
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c46
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h119
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c32
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c53
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h37
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc192
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c29
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h25
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h34
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c187
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h28
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h20
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc123
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c22
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h24
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h32
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c21
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h13
-rw-r--r--standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c16
-rw-r--r--standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java1
-rw-r--r--standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java139
80 files changed, 2390 insertions, 377 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b626eb0..8bfe32c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -189,7 +189,7 @@ jobs:
run: ./gradlew standalone:run --args="list-libs"
- name: Test
- run: ./gradlew standalone:test
+ run: ./gradlew standalone:test --continue
- name: Upload build artifacts
uses: actions/upload-artifact@v4
@@ -205,8 +205,25 @@ jobs:
path: |
standalone/build/results/
+ - name: Upload tests
+ uses: actions/upload-artifact@v4
+ with:
+ name: tests-standalone-${{ matrix.java }}
+ path: |
+ standalone/build/reports/tests/test/
+
- name: Upload code coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: crocs-muni/ECTester
+
+ - name: Upload test coverage
+ uses: codecov/test-results-action@v1
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ slug: crocs-muni/ECTester
+ files: >-
+ standalone/build/test-results/test/TEST-cz.crcs.ectester.standalone.AppTests.xml, standalone/build/test-results/test/TEST-cz.crcs.ectester.standalone.DeterministicTests.xml,
+ standalone/build/test-results/test/TEST-cz.crcs.ectester.standalone.IdentTests.xml, standalone/build/test-results/test/TEST-cz.crcs.ectester.standalone.LibTests.xml,
+ standalone/build/test-results/test/TEST-cz.crcs.ectester.standalone.OutputTests.xml
diff --git a/README.md b/README.md
index 726be68..379f05f 100644
--- a/README.md
+++ b/README.md
@@ -440,103 +440,121 @@ To install, place them in `${java.home}/jre/lib/security/`.
Snippet below shows how the `list-libs` command for well, listing currently supported libraries, behaves if all supported libraries are present (on Linux).
```
> java -jar ECTesterStandalone.jar list-libs
- - Sun Elliptic Curve provider
- - Version: 21.000000
+ - SunEC
+ - Fullname: SunEC
+ - Version: 21
- Supports native timing: []
- - KeyPairGenerators: EC
- - KeyAgreements: ECDH
- - Signatures: SHA3-256withECDSA, NONEwithECDSA, ECDSA, SHA3-384withECDSA, SHA384withECDSA, SHA3-512withECDSA, SHA224withECDSA, SHA512withECDSA, SHA3-224withECDSA, SHA256withECDSA
+ - Supports deterministic PRNG: true
+ - KeyPairGenerators: EC, Ed25519, Ed448, EdDSA, X25519, X448, XDH
+ - KeyAgreements: ECDH, X25519, X448, XDH
+ - Signatures: ECDSA, Ed25519, Ed448, EdDSA, NONEwithECDSA, SHA224withECDSA, SHA256withECDSA, SHA3-224withECDSA, SHA3-256withECDSA, SHA3-384withECDSA, SHA3-512withECDSA, SHA384withECDSA, SHA512withECDSA
- Curves: secp256r1, secp384r1, secp521r1
- - BouncyCastle Security Provider v1.77
- - Version: 1.770000
+ - BouncyCastle
+ - Fullname: BC
+ - Version: 1.77
- Supports native timing: []
- - KeyPairGenerators: ECDSA, ECMQV, EC, ECDH, ECDHC
- - KeyAgreements: ECCDHwithSHA384KDF, ECDHwithSHA384KDF, ECDHwithSHA256KDF, ECDHwithSHA1KDF, ECDHwithSHA224KDF, ECDH, ECDHC, ECDHwithSHA512KDF, ECCDHwithSHA1KDF, ECCDHwithSHA512KDF, ECCDHwithSHA224KDF, ECCDHwithSHA256KDF
- - Signatures: SHA1withCVC-ECDSA, NONEwithECDSA, ECGOST3410, SHA256withECNR, ECGOST3410-2012-512, SHA512withECDDSA, GOST3411-2012-512withECGOST3410-2012-512, SHA3-512withECDSA, SHA384withPLAIN-ECDSA, SHA256withECDSA, SHA256withECDDSA, SHA224withECDDSA, SHA3-256withECDSA, ECDSA, SHA256withPLAIN-ECDSA, SHA224withECNR, SHA384withECDDSA, SHA512withECNR, SHA256withCVC-ECDSA, SHA1withECNR, ECDDSA, SHA1withPLAIN-ECDSA, GOST3411-2012-256withECGOST3410-2012-256, SHA512withPLAIN-ECDSA, SHA384withCVC-ECDSA, SHA224withCVC-ECDSA, SHA3-224withECDSA, SHA3-224withECDDSA, SHA224withPLAIN-ECDSA, SHA3-384withECDDSA, SHA384withECDSA, SHA3-384withECDSA, SHA3-512withECDDSA, SM3withSM2, GOST3411withECGOST3410, ECGOST3410-2012-256, SHA224withECDSA, SHA512withECDSA, RIPEMD160withECDSA, SHA512withCVC-ECDSA, RIPEMD160withPLAIN-ECDSA, SHA3-256withECDDSA
+ - Supports deterministic PRNG: true
+ - KeyPairGenerators: EC, ECDH, ECDHC, ECDSA, ECMQV, Ed25519, Ed448, EdDSA, X25519, X448, XDH
+ - KeyAgreements: ECCDHwithSHA1KDF, ECCDHwithSHA224KDF, ECCDHwithSHA256KDF, ECCDHwithSHA384KDF, ECCDHwithSHA512KDF, ECDH, ECDHC, ECDHwithSHA1KDF, ECDHwithSHA224KDF, ECDHwithSHA256KDF, ECDHwithSHA384KDF, ECDHwithSHA512KDF, X25519, X448, XDH
+ - Signatures: ECDDSA, ECDSA, ECGOST3410, ECGOST3410-2012-256, ECGOST3410-2012-512, Ed25519, Ed448, EdDSA, GOST3411-2012-256withECGOST3410-2012-256, GOST3411-2012-512withECGOST3410-2012-512, GOST3411withECGOST3410, NONEwithECDSA, RIPEMD160withECDSA, RIPEMD160withPLAIN-ECDSA, SHA1withCVC-ECDSA, SHA1withECNR, SHA1withPLAIN-ECDSA, SHA224withCVC-ECDSA, SHA224withECDDSA, SHA224withECDSA, SHA224withECNR, SHA224withPLAIN-ECDSA, SHA256withCVC-ECDSA, SHA256withECDDSA, SHA256withECDSA, SHA256withECNR, SHA256withPLAIN-ECDSA, SHA3-224withECDDSA, SHA3-224withECDSA, SHA3-256withECDDSA, SHA3-256withECDSA, SHA3-384withECDDSA, SHA3-384withECDSA, SHA3-512withECDDSA, SHA3-512withECDSA, SHA384withCVC-ECDSA, SHA384withECDDSA, SHA384withECDSA, SHA384withPLAIN-ECDSA, SHA512withCVC-ECDSA, SHA512withECDDSA, SHA512withECDSA, SHA512withECNR, SHA512withPLAIN-ECDSA, SM3withSM2
- Curves: B-163, B-233, B-283, B-409, B-571, FRP256v1, GostR3410-2001-CryptoPro-A, GostR3410-2001-CryptoPro-B, GostR3410-2001-CryptoPro-C, GostR3410-2001-CryptoPro-XchA, GostR3410-2001-CryptoPro-XchB, K-163, K-233, K-283, K-409, K-571, P-192, P-224, P-256, P-384, P-521, Tc26-Gost-3410-12-256-paramSetA, Tc26-Gost-3410-12-512-paramSetA, Tc26-Gost-3410-12-512-paramSetB, Tc26-Gost-3410-12-512-paramSetC, brainpoolP160r1, brainpoolP160t1, brainpoolP192r1, brainpoolP192t1, brainpoolP224r1, brainpoolP224t1, brainpoolP256r1, brainpoolP256t1, brainpoolP320r1, brainpoolP320t1, brainpoolP384r1, brainpoolP384t1, brainpoolP512r1, brainpoolP512t1, c2pnb163v1, c2pnb163v2, c2pnb163v3, c2pnb176w1, c2pnb208w1, c2pnb272w1, c2pnb304w1, c2pnb368w1, c2tnb191v1, c2tnb191v2, c2tnb191v3, c2tnb239v1, c2tnb239v2, c2tnb239v3, c2tnb359v1, c2tnb431r1, prime192v1, prime192v2, prime192v3, prime239v1, prime239v2, prime239v3, prime256v1, secp112r1, secp112r2, secp128r1, secp128r2, secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1, sect113r1, sect113r2, sect131r1, sect131r2, sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, sm2p256v1, wapi192v1, wapip192v1
- - libtomcrypt 1.18.2
- - Version: 1.000000
+ - tomcrypt
+ - Fullname: libtomcrypt 1.18.2
+ - Version: 1.18
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
+ - Supports deterministic PRNG: true
- KeyPairGenerators: EC
- KeyAgreements: ECDH
- Signatures: NONEwithECDSA
- Curves: ECC-192, ECC-224, ECC-256, ECC-384, ECC-521, SECP112R1, SECP128R1, SECP160R1
- - Botan 2.19.3 (release, dated 20221116, revision git:15dc32f12d05e99a267f0fc47d88b678b71b8b05, distribution unspecified)
- - Version: 2.000000
+ - Botan
+ - Fullname: Botan 2.19.5
+ - Version: 2.193
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
- - KeyPairGenerators: ECGDSA, ECKCDSA, ECDSA, ECDH
- - KeyAgreements: ECDHwithSHA384KDF, ECDHwithSHA256KDF, ECDHwithSHA1KDF, ECDHwithSHA224KDF, ECDH, ECDHwithSHA512KDF
- - Signatures: NONEwithECDSA, NONEwithECKCDSA, SHA256withECKCDSA, SHA512withECGDSA, SHA256withECDSA, NONEwithECGDSA, ECKCDSA, ECDSA, SHA224withECKCDSA, SHA384withECKCDSA, SHA224withECGDSA, SHA384withECDSA, ECGDSA, SHA384withECGDSA, SHA224withECDSA, SHA512withECDSA, SHA512withECKCDSA
+ - Supports deterministic PRNG: true
+ - KeyPairGenerators: ECDH, ECDSA, ECGDSA, ECKCDSA
+ - KeyAgreements: ECDH, ECDHwithSHA1KDF, ECDHwithSHA224KDF, ECDHwithSHA256KDF, ECDHwithSHA384KDF, ECDHwithSHA512KDF
+ - Signatures: ECDSA, ECGDSA, ECKCDSA, NONEwithECDSA, NONEwithECGDSA, NONEwithECKCDSA, SHA224withECDSA, SHA224withECGDSA, SHA224withECKCDSA, SHA256withECDSA, SHA256withECKCDSA, SHA384withECDSA, SHA384withECGDSA, SHA384withECKCDSA, SHA512withECDSA, SHA512withECGDSA, SHA512withECKCDSA
- Curves: brainpool160r1, brainpool192r1, brainpool224r1, brainpool256r1, brainpool320r1, brainpool384r1, brainpool512r1, frp256v1, gost_256A, gost_512A, secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1, sm2p256v1, x962_p192v2, x962_p192v3, x962_p239v1, x962_p239v2, x962_p239v3
- - Crypto++ 8.9.0
- - Version: 8.000000
+ - Crypto++
+ - Fullname: Crypto++
+ - Version: 8.0
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
- - KeyPairGenerators: ECDSA, ECDH
+ - Supports deterministic PRNG: true
+ - KeyPairGenerators: ECDH, ECDSA
- KeyAgreements: ECDH
- - Signatures: ECDSA, SHA384withECDSA, SHA224withECDSA, SHA512withECDSA, SHA256withECDSA
+ - Signatures: ECDSA, SHA224withECDSA, SHA256withECDSA, SHA384withECDSA, SHA512withECDSA
- Curves: 1.2.156.10197.1.301, 1.2.156.10197.1.301.3.1, 1.2.840.10045.3.1.1, 1.2.840.10045.3.1.7, 1.3.132.0.1, 1.3.132.0.10, 1.3.132.0.15, 1.3.132.0.16, 1.3.132.0.17, 1.3.132.0.2, 1.3.132.0.22, 1.3.132.0.23, 1.3.132.0.24, 1.3.132.0.25, 1.3.132.0.26, 1.3.132.0.27, 1.3.132.0.28, 1.3.132.0.29, 1.3.132.0.3, 1.3.132.0.30, 1.3.132.0.31, 1.3.132.0.32, 1.3.132.0.33, 1.3.132.0.34, 1.3.132.0.35, 1.3.132.0.36, 1.3.132.0.37, 1.3.132.0.38, 1.3.132.0.39, 1.3.132.0.4, 1.3.132.0.5, 1.3.132.0.6, 1.3.132.0.7, 1.3.132.0.8, 1.3.132.0.9, 1.3.36.3.3.2.8.1.1.1, 1.3.36.3.3.2.8.1.1.11, 1.3.36.3.3.2.8.1.1.13, 1.3.36.3.3.2.8.1.1.3, 1.3.36.3.3.2.8.1.1.5, 1.3.36.3.3.2.8.1.1.7, 1.3.36.3.3.2.8.1.1.9
- - OpenSSL 3.2.1 30 Jan 2024
- - Version: 3.200000
+ - OpenSSL
+ - Fullname: OpenSSL 3.2.1 30 Jan 2024
+ - Version: 3.2
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
+ - Supports deterministic PRNG: true
- KeyPairGenerators: EC
- KeyAgreements: ECDH
- Signatures: NONEwithECDSA
- Curves: Oakley-EC2N-3, Oakley-EC2N-4, SM2, brainpoolP160r1, brainpoolP160t1, brainpoolP192r1, brainpoolP192t1, brainpoolP224r1, brainpoolP224t1, brainpoolP256r1, brainpoolP256t1, brainpoolP320r1, brainpoolP320t1, brainpoolP384r1, brainpoolP384t1, brainpoolP512r1, brainpoolP512t1, c2pnb163v1, c2pnb163v2, c2pnb163v3, c2pnb176v1, c2pnb208w1, c2pnb272w1, c2pnb304w1, c2pnb368w1, c2tnb191v1, c2tnb191v2, c2tnb191v3, c2tnb239v1, c2tnb239v2, c2tnb239v3, c2tnb359v1, c2tnb431r1, prime192v1, prime192v2, prime192v3, prime239v1, prime239v2, prime239v3, prime256v1, secp112r1, secp112r2, secp128r1, secp128r2, secp160k1, secp160r1, secp160r2, secp192k1, secp224k1, secp224r1, secp256k1, secp384r1, secp521r1, sect113r1, sect113r2, sect131r1, sect131r2, sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, wap-wsg-idm-ecid-wtls1, wap-wsg-idm-ecid-wtls10, wap-wsg-idm-ecid-wtls11, wap-wsg-idm-ecid-wtls12, wap-wsg-idm-ecid-wtls3, wap-wsg-idm-ecid-wtls4, wap-wsg-idm-ecid-wtls5, wap-wsg-idm-ecid-wtls6, wap-wsg-idm-ecid-wtls7, wap-wsg-idm-ecid-wtls8, wap-wsg-idm-ecid-wtls9
- - OpenSSL 1.1.1 (compatible; BoringSSL)
- - Version: 1.110000
+ - BoringSSL
+ - Fullname: OpenSSL 1.1.1 (compatible; BoringSSL)
+ - Version: 1.11
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
+ - Supports deterministic PRNG: false
- KeyPairGenerators: EC
- KeyAgreements: ECDH
- Signatures: NONEwithECDSA
- Curves: prime256v1, secp224r1, secp384r1, secp521r1
- - libgcrypt 1.10.3-unknown
- - Version: 1.000000
+ - libgcrypt
+ - Fullname: libgcrypt 1.11.0-unknown
+ - Version: 1.11
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
+ - Supports deterministic PRNG: false
- KeyPairGenerators: EC
- KeyAgreements: ECDH
- - Signatures: SHA224withECDDSA, SHA256withECDDSA, NONEwithECDSA, ECDSA, ECDDSA, SHA384withECDSA, SHA512withECDDSA, SHA224withECDSA, SHA512withECDSA, SHA384withECDDSA, SHA256withECDSA
+ - Signatures: ECDDSA, ECDSA, NONEwithECDSA, SHA224withECDDSA, SHA224withECDSA, SHA256withECDDSA, SHA256withECDSA, SHA384withECDDSA, SHA384withECDSA, SHA512withECDDSA, SHA512withECDSA
- Curves: Curve25519, Ed25519, Ed448, GOST2001-CryptoPro-A, GOST2001-CryptoPro-B, GOST2001-CryptoPro-C, GOST2001-test, GOST2012-256-A, GOST2012-512-tc26-A, GOST2012-512-tc26-B, GOST2012-512-tc26-C, GOST2012-512-test, NIST P-192, NIST P-224, NIST P-256, NIST P-384, NIST P-521, X448, brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, brainpoolP320r1, brainpoolP384r1, brainpoolP512r1, secp256k1, sm2p256v1
- - wolfCrypt JCE Provider
- - Version: 1.500000
- - Supports native timing: []
- - KeyAgreements: ECDH
- - Signatures: ECDSA, SHA384withECDSA, SHA512withECDSA, SHA256withECDSA
-
- - Mbed TLS 3.5.2
- - Version: 3.000000
+ - mbedTLS
+ - Fullname: Mbed TLS 3.5.2
+ - Version: 3.52
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
+ - Supports deterministic PRNG: true
- KeyPairGenerators: EC
- KeyAgreements: ECDH
- Signatures: NONEwithECDSA
- Curves: brainpoolP256r1, brainpoolP384r1, brainpoolP512r1, secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1, x25519, x448
- - 2021.7.0 (11.5 ) (-)
- - Version: 2021.700000
+ - IPPCP
+ - Fullname: ippCP AVX2 (l9)
+ - Version: 2021.7
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
+ - Supports deterministic PRNG: true
- KeyPairGenerators: EC
- KeyAgreements: ECDH
- Signatures: NONEwithECDSA
- Curves: secp112r1, secp112r2, secp128r1, secp128r2, secp160r1, secp160r2, secp192r1, secp224r1, secp256r1, secp384r1, secp521r1
- Nettle
- - Version: 3.900000
+ - Fullname: Nettle
+ - Version: 3.9
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
+ - Supports deterministic PRNG: true
- KeyPairGenerators: EC
- KeyAgreements: ECDH
- Signatures: NONEwithECDSA
- Curves: secp192r1, secp224r1, secp256r1, secp384r1, secp521r1
- - LibreSSL 3.9.0
- - Version: 3.900000
+ - LibreSSL
+ - Fullname: LibreSSL 3.9.0
+ - Version: 3.9
- Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc]
+ - Supports deterministic PRNG: false
- KeyPairGenerators: EC
- KeyAgreements: ECDH
- Signatures: NONEwithECDSA
@@ -559,7 +577,7 @@ index;time[nano];pubW;privS
Snippet below demonstrates performing 10 ECDSA signatures, without hashing the message (`-t NONEwithECDSA`) on the `secp256r1` curve, with a fixed keypair throught the process (`--fixed`), utilizing the rdtsc instruction to measure duration (`--time-source`) and using the MatrixSSL library.
```
-> java -jar ECTesterStandalone.jar ecdsa -n 10 -t NONEwithECDSA -nc secg/secp256r1 --fixed --time-source rdtsc Matrix
+> java -jar ECTesterStandalone.jar ecdsa -n 10 -t NONEwithECDSA -nc secg/secp256r1 --fixed --time-source rdtsc OpenSSL
index;signTime[instr];verifyTime[instr];data;pubW;privS;signature[NONE];nonce;verified
0;6785333;18200703;24b064ff5a4d08df6f982d0e139677fb4e66602bea01e381e16d4d3614fd09d5;0429ef9b52fc5c9b8711c938820f4d15d6aab1dcd8aa5a80e754233f23c622a5a174cca795068aff9c979bff7e6f1345b529612a4d16df6adf56b8ac250a1fafc3;54d06d1a79b2b43dc072b96ca7b9f045fda84ac13f74ef81fab0d561a47d11d1;3045022070ca3dfe2017892d23a2301b2465ab387af7999c79de7dae53ec04d1600a25800221009fc9a6fe20c7930b9d8be40424ab4b08fa641f339efa81e6ccf5497cd71180f0;57ebf83913734ff0a78fa952da12996c48da17fbcf5967e74eb3e2c6b5e726b1;1
1;8582180;16170010;24b064ff5a4d08df6f982d0e139677fb4e66602bea01e381e16d4d3614fd09d5;0429ef9b52fc5c9b8711c938820f4d15d6aab1dcd8aa5a80e754233f23c622a5a174cca795068aff9c979bff7e6f1345b529612a4d16df6adf56b8ac250a1fafc3;54d06d1a79b2b43dc072b96ca7b9f045fda84ac13f74ef81fab0d561a47d11d1;3045022100efd3efc1bb2ed243eec9bea4bc331966e869c02df1fc8686a7649708c106595a022050e9a2548bac56bb3287f27c1761136947eefaa8a92f31978ed9485a03cb8f3d;0f5d3cc25d3eb69177b7917631f5639a088773873e91c1adb0a2b753987cace8;1
@@ -571,7 +589,7 @@ index;signTime[instr];verifyTime[instr];data;pubW;privS;signature[NONE];nonce;ve
Snippet below demonstrates performing 10000 ECDH key agreements, using the curve name `secp256r1` (`-cn`, the difference between the `-cn` option and the `-nc` option is that the latter looks up the curve in ECTester's database and passes the parameters to the library explicitly, while the former passes the name to the library) using the MbedTLS library.
```
-> java -jar ECTesterStandalone.jar ecdh -n 10000 -cn secp256r1 mbed
+> java -jar ECTesterStandalone.jar ecdh -n 10000 -cn secp256r1 mbedTLS
index;time[nano];pubW;privS;secret[NONE]
0;5952101;04367ef86b5fbf1b4716bf7822342ebb19a9b6bcfbdb4f4950bf090ba2d1263579dac3e8447c21202432c76f89a0b48a1c16970e4fde67853c8d389da3f02fcdfc;00ecc7b46513149ab19fbeb1c49c1706712dc7da3899add30eb935e18fe5851d79;a94524fa98e0e5b3e139afdb89b73b843e48d5491b19585a5dcae02f20f13088
1;6099022;0439803db68efddbfc3fba1feae41118b02e35d009670fbb4c5dfe6a56fe20829b42e101d0c55bf905276ac71af7e215714cf41742c1f8a2d102761b9eb307d209;6f43118f50ddfef724288ad4f116354bec4735370cb221547b76b18832daaea9;d1b90ed000ca9542ac2101383397a7180cdcd6896b1ccfb5b719da734ad96bf1
@@ -585,6 +603,24 @@ index;time[nano];pubW;privS;secret[NONE]
...
```
+Snippet below demonstrates the support for using a deterministic PRNG (`-ps`) in some of the libraries (see the output of `list-libs`):
+```
+> java -jar ECTesterStandalone.jar generate -n 5 -ps 1234 -b 256 Bouncy
+index;time[nano];pubW;privS
+0;33664582;04db8bdd6cb30d08a0355d48b65ddfc123944d29395f9f5e1bc2bfe70b4ee44ad39e4005df1e61251b4e9a9d8d47b78fd4ce98181883d2bfd634743758397f54ae;00e08df38827302c3315b833022189f61af3af9fbcb6e53697724374861f1982ee
+1;3584575;0458bc7baf831c1a316a8deb9fb3109841f10d3cb8828b583b9883a518fa04633488e2fa991e70c98612c989fdfd6aa25118947e8a17bfc36ad1f51a8bdc473e3d;0f5a481f518751bbd2112e4fcc3d1ac60cd66a474af9a57cedbd1e62a52b6bd9
+2;2746750;04827d7247b6d478cc85df313a9ea4f102301b0bd125b18e0111cd02e53b319830b2d0218551504cfc6b1226ac7fa430388f677cab2ea36997e344078328d12207;222898920190d28dac732b8e1fa69dd9907c667604c54db70c41b4815eafc94b
+3;2828535;0473104cec678c5ea20857435f19280975c2a3b2d22e7f8005c33d019de6b707012960b96a80f0f358a69dcd5dd34c748cae3fa9f45b720f5a7d241017010c1af1;3fb2f7c3a15f86f000017e42f79557befe7472ff462d3321bc13a043c251345c
+4;14181365;04854011114eb3e0fcf21f2416e0adbb0fc81d84530860ca40b6a86c85aa4e66b455382b71f8b6144f6294376912334ff1b23bb49da8fe1bda0e0e89ccbe9145f6;65675a954fff3287be1fc61dbb176f6784ece16c6b5675d556c57fd58974b358
+> java -jar ECTesterStandalone.jar generate -n 5 -ps 1234 -b 256 Bouncy
+index;time[nano];pubW;privS
+0;35138528;04db8bdd6cb30d08a0355d48b65ddfc123944d29395f9f5e1bc2bfe70b4ee44ad39e4005df1e61251b4e9a9d8d47b78fd4ce98181883d2bfd634743758397f54ae;00e08df38827302c3315b833022189f61af3af9fbcb6e53697724374861f1982ee
+1;2351304;0458bc7baf831c1a316a8deb9fb3109841f10d3cb8828b583b9883a518fa04633488e2fa991e70c98612c989fdfd6aa25118947e8a17bfc36ad1f51a8bdc473e3d;0f5a481f518751bbd2112e4fcc3d1ac60cd66a474af9a57cedbd1e62a52b6bd9
+2;3315124;04827d7247b6d478cc85df313a9ea4f102301b0bd125b18e0111cd02e53b319830b2d0218551504cfc6b1226ac7fa430388f677cab2ea36997e344078328d12207;222898920190d28dac732b8e1fa69dd9907c667604c54db70c41b4815eafc94b
+3;2883430;0473104cec678c5ea20857435f19280975c2a3b2d22e7f8005c33d019de6b707012960b96a80f0f358a69dcd5dd34c748cae3fa9f45b720f5a7d241017010c1af1;3fb2f7c3a15f86f000017e42f79557befe7472ff462d3321bc13a043c251345c
+4;2060970;04854011114eb3e0fcf21f2416e0adbb0fc81d84530860ca40b6a86c85aa4e66b455382b71f8b6144f6294376912334ff1b23bb49da8fe1bda0e0e89ccbe9145f6;65675a954fff3287be1fc61dbb176f6784ece16c6b5675d556c57fd58974b358
+```
+
It is recommended to disable [CPU frequency scaling](https://wiki.archlinux.org/index.php/CPU_frequency_scaling) of your processor before performing collection of timing data, as it adds significant noise to the data as it kicks in. Also, running the collection on very high priority and locked to a single core (`taskset -c 0`) helps as well.
## Analysis
diff --git a/common/src/main/java/cz/crcs/ectester/common/util/Util.java b/common/src/main/java/cz/crcs/ectester/common/util/Util.java
index 5b0cd79..1d9bcf4 100644
--- a/common/src/main/java/cz/crcs/ectester/common/util/Util.java
+++ b/common/src/main/java/cz/crcs/ectester/common/util/Util.java
@@ -1,5 +1,8 @@
package cz.crcs.ectester.common.util;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
/**
* @author Jan Jancar johny@neuromancer.sk
*/
@@ -18,11 +21,25 @@ public class Util {
public static int getVersion() {
String version = System.getProperty("java.version");
- if(version.startsWith("1.")) {
+ if (version.startsWith("1.")) {
version = version.substring(2, 3);
} else {
int dot = version.indexOf(".");
- if(dot != -1) { version = version.substring(0, dot); }
- } return Integer.parseInt(version);
+ if (dot != -1) {
+ version = version.substring(0, dot);
+ }
+ }
+ return Integer.parseInt(version);
+ }
+
+ public static SecureRandom getRandom(byte[] seed) {
+ SecureRandom random;
+ try {
+ random = SecureRandom.getInstance("SHA1PRNG");
+ } catch (NoSuchAlgorithmException ignored) {
+ return null;
+ }
+ random.setSeed(seed);
+ return random;
}
}
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 91f4653..6f624a0 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java
@@ -69,7 +69,7 @@ public class ECTesterReader {
public static final String VERSION = "v0.3.3";
public static String GIT_COMMIT = "";
private static String DESCRIPTION;
- private static String LICENSE = "MIT Licensed\nCopyright © 2016-2019 Petr Svenda <petr@svenda.com>\nCopyright © 2016-2019 Jan Jancar <johny@neuromancer.sk>";
+ private static String LICENSE = "MIT Licensed\nCopyright © 2016-2024 Petr Svenda <petr@svenda.com>\nCopyright © 2016-2024 Jan Jancar <johny@neuromancer.sk>";
private static String CLI_HEADER;
private static String CLI_FOOTER = "\n" + LICENSE;
@@ -86,13 +86,15 @@ public class ECTesterReader {
ClassLoader cl = ECTesterReader.class.getClassLoader();
try {
URL url = cl.getResource("META-INF/MANIFEST.MF");
- Manifest manifest = new Manifest(url.openStream());
- String commit = manifest.getMainAttributes().getValue("Git-Commit");
- GIT_COMMIT = (commit == null) ? "" : "(git " + commit + ")";
+ if (url != null) {
+ Manifest manifest = new Manifest(url.openStream());
+ String commit = manifest.getMainAttributes().getValue("Git-Commit");
+ GIT_COMMIT = (commit == null) ? "" : "(git " + commit + ")";
+ }
} catch (Exception ignored) {
}
- DESCRIPTION = "ECTesterReader " + VERSION + GIT_COMMIT + ", a javacard Elliptic Curve Cryptography support tester/utility.";
+ DESCRIPTION = "ECTesterReader " + VERSION + GIT_COMMIT + ", a JavaCard Elliptic Curve Cryptography tester/utility.";
CLI_HEADER = "\n" + DESCRIPTION + "\n\n";
}
@@ -338,10 +340,11 @@ public class ECTesterReader {
opts.addOption(Option.builder("f").longOpt("fresh").desc("Generate fresh keys (set domain parameters before every generation).").build());
opts.addOption(Option.builder().longOpt("time").desc("Output better timing values, by running command in dry run mode and normal mode, and subtracting the two.").build());
opts.addOption(Option.builder().longOpt("time-unit").desc("Use given time unit in measurement, one of: milli, micro, nano.").hasArg().argName("unit").build());
- opts.addOption(Option.builder().longOpt("cleanup").desc("Send the cleanup command trigerring JCSystem.requestObjectDeletion() after some operations.").build());
+ opts.addOption(Option.builder().longOpt("cleanup").desc("Send the cleanup command triggering JCSystem.requestObjectDeletion() after some operations.").build());
opts.addOption(Option.builder("s").longOpt("simulate").desc("Simulate a card with jcardsim instead of using a terminal.").build());
opts.addOption(Option.builder("y").longOpt("yes").desc("Accept all warnings and prompts.").build());
- opts.addOption(Option.builder("to").longOpt("test-options").desc("Test options to use:\n- preset: Use preset semi-random private keys (derived from curve) instead of generating keypairs on the cards when the test needs one.\n- random: Use fully random private keys instead of generating keypairs.").hasArg().argName("options").build());
+ opts.addOption(Option.builder("tk").longOpt("test-key").desc("Key setup technique to use in test suites:\n- generate (default): Generate keypairs on the card.\n- deterministic: Prepare keypairs deterministically off-card.\n- random: Prepare keypairs randomly off-card.").hasArg().argName("option").build());
+ opts.addOption(Option.builder("td").longOpt("test-data").desc("Data setup technique to use in test suites:\n- random (default): Prepare data randomly off-card.\n- deterministic: Prepare data deterministically off-card.").hasArg().argName("option").build());
opts.addOption(Option.builder("ka").longOpt("ka-type").desc("Set KeyAgreement object [type], corresponds to JC.KeyAgreement constants.").hasArg().argName("type").optionalArg(true).build());
opts.addOption(Option.builder("sig").longOpt("sig-type").desc("Set Signature object [type], corresponds to JC.Signature constants.").hasArg().argName("type").optionalArg(true).build());
@@ -370,9 +373,6 @@ public class ECTesterReader {
for (String line : suite.getDescription()) {
System.out.println("\t" + line);
}
- if (suite.getOptions() != null) {
- System.out.println("\t" + Colors.underline("Options:") + " " + Arrays.toString(suite.getOptions()));
- }
}
System.out.println();
System.out.println("For more information, look at the documentation at https://github.com/crocs-muni/ECTester.");
@@ -380,13 +380,13 @@ public class ECTesterReader {
private void info() throws CardException {
Response.GetInfo info = new Command.GetInfo(cardManager).send();
- System.out.println(String.format("Card ATR:\t\t\t\t%s", ByteUtil.bytesToHex(cardManager.getATR().getBytes(), false)));
- System.out.println(String.format("Card protocol:\t\t\t\t%s", cardManager.getProtocol()));
- System.out.println(String.format("ECTester applet version:\t\t%s", info.getVersion()));
- System.out.println(String.format("ECTester applet APDU support:\t\t%s", (info.getBase() == CardConsts.BASE_221) ? "basic" : "extended length"));
- System.out.println(String.format("JavaCard API version:\t\t\t%.1f", info.getJavaCardVersion()));
- System.out.println(String.format("JavaCard supports system cleanup:\t%s", info.getCleanupSupport()));
- System.out.println(String.format("Array sizes (apduBuf,ram,ram2,apduArr):\t%d %d %d %d", info.getApduBufferLength(), info.getRamArrayLength(), info.getRamArray2Length(), info.getApduArrayLength()));
+ System.out.printf("Card ATR:\t\t\t\t%s%n", ByteUtil.bytesToHex(cardManager.getATR().getBytes(), false));
+ System.out.printf("Card protocol:\t\t\t\t%s%n", cardManager.getProtocol());
+ System.out.printf("ECTester applet version:\t\t%s%n", info.getVersion());
+ System.out.printf("ECTester applet APDU support:\t\t%s%n", (info.getBase() == CardConsts.BASE_221) ? "basic" : "extended length");
+ System.out.printf("JavaCard API version:\t\t\t%.1f%n", info.getJavaCardVersion());
+ System.out.printf("JavaCard supports system cleanup:\t%s%n", info.getCleanupSupport());
+ System.out.printf("Array sizes (apduBuf,ram,ram2,apduArr):\t%d %d %d %d%n", info.getApduBufferLength(), info.getRamArrayLength(), info.getRamArray2Length(), info.getApduArrayLength());
}
/**
@@ -866,7 +866,8 @@ public class ECTesterReader {
public byte ECKAType = EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
public int ECDSACount;
public byte ECDSAType = EC_Consts.Signature_ALG_ECDSA_SHA;
- public Set<String> testOptions;
+ public String testKeySetup;
+ public String testDataSetup;
/**
* Reads and validates options, also sets defaults.
@@ -1044,25 +1045,20 @@ public class ECTesterReader {
testSuite = selected;
}
- String[] opts = cli.getOptionValue("test-options", "").split(",");
- List<String> validOpts = Arrays.asList("preset", "random");
- testOptions = new HashSet<>();
- for (String opt : opts) {
- if (opt.equals("")) {
- continue;
- }
- if (!validOpts.contains(opt)) {
- System.err.println(Colors.error("Unknown test option " + opt + ". Should be one of: " + Arrays.toString(validOpts.toArray())));
- return false;
- } else {
- testOptions.add(opt);
- }
+ testKeySetup = cli.getOptionValue("test-key", "generate");
+ List<String> testKeyOpts = Arrays.asList("generate", "deterministic", "random");
+ if (!testKeyOpts.contains(testKeySetup)) {
+ System.err.println(Colors.error("Unknown test option " + testKeySetup + ". Should be one of: " + Arrays.toString(testKeyOpts.toArray())));
+ return false;
}
- if (testOptions.contains("preset") && testOptions.contains("random")) {
- System.err.println("Cannot have both preset and random option enabled.");
+ testDataSetup = cli.getOptionValue("test-data", "random");
+ List<String> testDataOpts = Arrays.asList("deterministic", "random");
+ if (!testDataOpts.contains(testDataSetup)) {
+ System.err.println(Colors.error("Unknown test option " + testDataSetup + ". Should be one of: " + Arrays.toString(testDataOpts.toArray())));
return false;
}
+
} else if (cli.hasOption("ecdh")) {
if (primeField == binaryField) {
System.err.print(Colors.error("Need to specify field with -fp or -f2m. (not both)"));
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/output/TextTestWriter.java b/reader/src/main/java/cz/crcs/ectester/reader/output/TextTestWriter.java
index 532ace5..3ba5431 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/output/TextTestWriter.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/output/TextTestWriter.java
@@ -52,7 +52,8 @@ public class TextTestWriter extends BaseTextTestWriter {
sb.append("═══ ").append(Colors.underline("Card ATR:")).append(" ").append(ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false)).append(System.lineSeparator());
sb.append("═══ ").append(Colors.underline("JavaCard version:")).append(" ").append(info.getJavaCardVersion()).append(System.lineSeparator());
sb.append("═══ ").append(Colors.underline("Array sizes (apduBuf, ram, ram2, apduArr):")).append(" ").append(String.format("%d %d %d %d", info.getApduBufferLength(), info.getRamArrayLength(), info.getRamArray2Length(), info.getApduArrayLength())).append(System.lineSeparator());
- sb.append("═══ ").append(Colors.underline("Test options:")).append(" ").append(String.join(",", cardSuite.getCfg().testOptions)).append(System.lineSeparator());
+ sb.append("═══ ").append(Colors.underline("Test key setup:")).append(" ").append(cardSuite.getCfg().testKeySetup).append(System.lineSeparator());
+ sb.append("═══ ").append(Colors.underline("Test data setup:")).append(" ").append(cardSuite.getCfg().testDataSetup).append(System.lineSeparator());
CardMngr.CPLC cplc = cardSuite.getCard().getCPLC();
if (!cplc.values().isEmpty()) {
sb.append("═══ ").append(Colors.underline("Card CPLC data:")).append(System.lineSeparator());
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardCofactorSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardCofactorSuite.java
index 01e9d02..b0ad2d3 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardCofactorSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardCofactorSuite.java
@@ -5,7 +5,6 @@ import cz.crcs.ectester.common.ec.EC_Key;
import cz.crcs.ectester.common.ec.EC_Consts;
import cz.crcs.ectester.common.output.TestWriter;
import cz.crcs.ectester.common.test.CompoundTest;
-import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.Test;
import cz.crcs.ectester.common.util.CardUtil;
import cz.crcs.ectester.common.util.CardConsts;
@@ -25,7 +24,7 @@ import static cz.crcs.ectester.common.test.Result.ExpectedValue;
*/
public class CardCofactorSuite extends CardTestSuite {
public CardCofactorSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "cofactor", new String[]{"preset", "random"}, "The cofactor test suite tests whether the card correctly rejects points on the curve",
+ super(writer, cfg, cardManager, "cofactor", "The cofactor test suite tests whether the card correctly rejects points on the curve",
"but not in the subgroup generated by the generator(so of small order, dividing the cofactor) during ECDH.");
}
@@ -45,12 +44,12 @@ public class CardCofactorSuite extends CardTestSuite {
List<Test> ecdhTests = new LinkedList<>();
for (EC_Key.Public pub : keys) {
- Test setPub = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Result.ExpectedValue.FAILURE);
- Test ecdh = CommandTest.expect(new Command.ECDH(this.card, CardConsts.KEYPAIR_REMOTE, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE);
- Test objectEcdh = CompoundTest.any(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with cofactor pubkey.", setPub, ecdh);
+ Test setPub = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), ExpectedValue.FAILURE);
+ Test ecdh = CommandTest.expect(new Command.ECDH(this.card, CardConsts.KEYPAIR_REMOTE, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ExpectedValue.FAILURE);
+ Test objectEcdh = CompoundTest.any(ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with cofactor pubkey.", setPub, ecdh);
Command ecdhCommand = new Command.ECDH_direct(this.card, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
Test rawEcdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on non-generator subgroup.", "Card incorrectly accepted point on non-generator subgroup.");
- ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " cofactor key test.", objectEcdh, rawEcdh));
+ ecdhTests.add(CompoundTest.all(ExpectedValue.SUCCESS, pub.getId() + " cofactor key test.", objectEcdh, rawEcdh));
}
Test ecdh = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH with public points on non-generator subgroup.", ecdhTests.toArray(new Test[0]));
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardCompositeSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardCompositeSuite.java
index bba211a..71890e1 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardCompositeSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardCompositeSuite.java
@@ -6,7 +6,6 @@ import cz.crcs.ectester.common.ec.EC_Consts;
import cz.crcs.ectester.common.output.TestWriter;
import cz.crcs.ectester.common.test.CompoundTest;
import cz.crcs.ectester.common.test.Test;
-import cz.crcs.ectester.common.util.CardUtil;
import cz.crcs.ectester.common.util.CardConsts;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.reader.CardMngr;
@@ -25,7 +24,7 @@ import static cz.crcs.ectester.common.test.Result.ExpectedValue;
public class CardCompositeSuite extends CardTestSuite {
public CardCompositeSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "composite", new String[]{"preset", "random"}, "The composite suite runs ECDH over curves with composite order.",
+ super(writer, cfg, cardManager, "composite", "The composite suite runs ECDH over curves with composite order.",
"Various types of compositeness is tested: smooth numbers, Carmichael pseudo-prime, prime square, product of two large primes.");
}
@@ -39,19 +38,13 @@ public class CardCompositeSuite extends CardTestSuite {
Test allocate = CommandTest.expect(new Command.Allocate(this.card, CardConsts.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS);
Test set = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_LOCAL, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY);
- String name;
- if (cfg.testOptions.contains("preset")) {
- name = "preset semi-random private key";
- } else {
- name = "generated private key";
- }
Test setKeypair = setupKeypairs(curve, ExpectedValue.ANY, CardConsts.KEYPAIR_LOCAL);
Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare keypair on " + curve.getId() + ".", allocate, set, setKeypair);
for (EC_Key key : curveKeys.getValue()) {
Command ecdhCommand = new Command.ECDH_direct(this.card, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, key.flatten());
Test ecdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a composite order curve.", "Card incorrectly does ECDH over a composite order curve, leaks bits of private key.");
- tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", with " + name + ", " + key.getDesc(), ecdh));
+ tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", with " + key.getDesc(), ecdh));
}
Test ecdhTest = CompoundTest.all(ExpectedValue.SUCCESS, "Do ECDH.", tests.toArray(new Test[0]));
doTest(CompoundTest.greedyAll(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ".", prepare, ecdhTest));
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardCompressionSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardCompressionSuite.java
index 418ed2f..3598224 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardCompressionSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardCompressionSuite.java
@@ -15,7 +15,6 @@ import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.reader.CardMngr;
import cz.crcs.ectester.reader.ECTesterReader;
import cz.crcs.ectester.reader.command.Command;
-import cz.crcs.ectester.reader.response.Response;
import java.security.spec.ECPoint;
import java.util.LinkedList;
@@ -79,7 +78,7 @@ public class CardCompressionSuite extends CardTestSuite {
compressionTests.add(genCustom);
EC_Curve secgCurve = EC_Store.getInstance().getObject(EC_Curve.class, "secg", CardUtil.getCurveName(curveId));
- ECPoint pub = ECUtil.toPoint(ECUtil.fixedRandomPoint(secgCurve));
+ ECPoint pub = ECUtil.toPoint(preparePubkey(secgCurve));
List<Test> kaTests = new LinkedList<>();
for (byte kaType : EC_Consts.KA_TYPES) {
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardDefaultSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardDefaultSuite.java
index c365d52..5ac8f1a 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardDefaultSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardDefaultSuite.java
@@ -27,7 +27,7 @@ import static cz.crcs.ectester.common.test.Result.Value;
public class CardDefaultSuite extends CardTestSuite {
public CardDefaultSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "default", null, "The default test suite tests basic support and performance of ECDH and ECDSA.");
+ super(writer, cfg, cardManager, "default", "The default test suite tests basic support and performance of ECDH and ECDSA.");
}
@Override
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardDegenerateSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardDegenerateSuite.java
index c731416..6817390 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardDegenerateSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardDegenerateSuite.java
@@ -24,7 +24,7 @@ import java.util.Map;
public class CardDegenerateSuite extends CardTestSuite {
public CardDegenerateSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "degenerate", null, "The degenerate suite tests whether the card rejects points outside of the curve during ECDH.",
+ super(writer, cfg, cardManager, "degenerate", "The degenerate suite tests whether the card rejects points outside of the curve during ECDH.",
"The tested points lie on a part of the plane for which some Edwards, Hessian and Huff form addition formulas degenerate into exponentiation in the base finite field.");
}
@@ -38,7 +38,7 @@ public class CardDegenerateSuite extends CardTestSuite {
Test allocate = CommandTest.expect(new Command.Allocate(this.card, CardConsts.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS);
Test set = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS);
- Test generate = CommandTest.expect(new Command.Generate(this.card, CardConsts.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS);
+ Test generate = setupKeypairs(curve, Result.ExpectedValue.SUCCESS, CardConsts.KEYPAIR_LOCAL);
Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate);
@@ -47,7 +47,7 @@ public class CardDegenerateSuite extends CardTestSuite {
Test setPub = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Result.ExpectedValue.FAILURE);
Test ecdh = CommandTest.expect(new Command.ECDH(this.card, CardConsts.KEYPAIR_REMOTE, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve.");
Test objectEcdh = CompoundTest.any(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with degenerate pubkey.", setPub, ecdh);
- Command ecdhCommand = new Command.ECDH_direct(this.card, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
+ Command ecdhCommand = new Command.ECDH_direct(this.card, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
Test rawEcdh = CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve.");
ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " degenerate key test.", objectEcdh, rawEcdh));
//TODO: actually get the result of ECDH here, as well as export privkey and compare to exponentiation in Fp^*.
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java
index fb24e30..00bc34e 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java
@@ -26,7 +26,7 @@ import java.util.stream.Collectors;
*/
public class CardEdgeCasesSuite extends CardTestSuite {
public CardEdgeCasesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "edge-cases", null, "The edge-cases test suite tests various inputs to ECDH which may cause an implementation to achieve a certain edge-case state during it.",
+ super(writer, cfg, cardManager, "edge-cases", "The edge-cases test suite tests various inputs to ECDH which may cause an implementation to achieve a certain edge-case state during it.",
"Some of the data is from the google/Wycheproof project. Tests include CVE-2017-10176 and CVE-2017-8932.",
"Also tests values of the private key and public key that would trigger the OpenSSL modular multiplication bug on the P-256 curve.",
"Various edge private key values are also tested.");
@@ -141,11 +141,12 @@ public class CardEdgeCasesSuite extends CardTestSuite {
List<EC_Curve> curves = curveMap.entrySet().stream().filter((e) -> e.getKey().endsWith("r1") && e.getValue().getField() == EC_Consts.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList());
curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor128p2"));
curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor160p4"));
- Random rand = new Random();
+
for (EC_Curve curve : curves) {
+ Random rand = setupRandom(curve);
Test key = CommandTest.expect(new Command.Allocate(this.card, CardConsts.KEYPAIR_BOTH, curve.getBits(), EC_Consts.ALG_EC_FP), Result.ExpectedValue.SUCCESS);
Test set = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS);
- Test generate = CommandTest.expect(new Command.Generate(this.card, CardConsts.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS);
+ Test generate = setupKeypairs(curve, Result.ExpectedValue.SUCCESS, CardConsts.KEYPAIR_LOCAL);
CommandTest export = CommandTest.expect(new Command.Export(this.card, CardConsts.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W), Result.ExpectedValue.SUCCESS);
Test setup = CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyPair setup.", key, set, generate, export);
@@ -237,6 +238,7 @@ public class CardEdgeCasesSuite extends CardTestSuite {
}
EC_Curve secp160r1 = EC_Store.getInstance().getObject(EC_Curve.class, "secg/secp160r1");
+ Random rand = setupRandom(secp160r1);
byte[] pData = secp160r1.getParam(EC_Consts.PARAMETER_FP)[0];
BigInteger p = new BigInteger(1, pData);
byte[] rData = secp160r1.getParam(EC_Consts.PARAMETER_R)[0];
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardInvalidSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardInvalidSuite.java
index 2fd457d..cacfba9 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardInvalidSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardInvalidSuite.java
@@ -26,7 +26,7 @@ import static cz.crcs.ectester.common.test.Result.ExpectedValue;
public class CardInvalidSuite extends CardTestSuite {
public CardInvalidSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "invalid", null, "The invalid curve suite tests whether the card rejects points outside of the curve during ECDH.");
+ super(writer, cfg, cardManager, "invalid", "The invalid curve suite tests whether the card rejects points outside of the curve during ECDH.");
}
@Override
@@ -42,7 +42,7 @@ public class CardInvalidSuite extends CardTestSuite {
Test allocate = CommandTest.expect(new Command.Allocate(this.card, CardConsts.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS);
Test set = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS);
- Test generate = CommandTest.expect(new Command.Generate(this.card, CardConsts.KEYPAIR_LOCAL), ExpectedValue.SUCCESS);
+ Test generate = setupKeypairs(curve, Result.ExpectedValue.SUCCESS, CardConsts.KEYPAIR_LOCAL);
Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate);
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardMiscSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardMiscSuite.java
index 3ffe07c..38dcf80 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardMiscSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardMiscSuite.java
@@ -24,7 +24,7 @@ import java.util.function.Function;
public class CardMiscSuite extends CardTestSuite {
public CardMiscSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "miscellaneous", new String[]{"preset", "random"}, "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves, anomalous curves,",
+ super(writer, cfg, cardManager, "miscellaneous", "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves, anomalous curves,",
"Barreto-Naehrig curves with small embedding degree and CM discriminant, MNT curves,",
"some Montgomery curves transformed to short Weierstrass form and Curve25519 transformed to short Weierstrass form.");
}
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardSignatureSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardSignatureSuite.java
index 086654a..0bf897a 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardSignatureSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardSignatureSuite.java
@@ -22,7 +22,7 @@ import java.util.Map;
*/
public class CardSignatureSuite extends CardTestSuite {
public CardSignatureSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "signature", null, "The signature test suite tests verifying various malformed and well-formed but invalid ECDSA signatures.");
+ super(writer, cfg, cardManager, "signature", "The signature test suite tests verifying various malformed and well-formed but invalid ECDSA signatures.");
}
@Override
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java
index 15c4469..e2d9dd1 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java
@@ -10,11 +10,13 @@ import cz.crcs.ectester.common.test.Test;
import cz.crcs.ectester.common.test.TestSuite;
import cz.crcs.ectester.common.util.CardConsts;
import cz.crcs.ectester.common.util.ECUtil;
+import cz.crcs.ectester.common.util.Util;
import cz.crcs.ectester.reader.CardMngr;
import cz.crcs.ectester.reader.ECTesterReader;
import cz.crcs.ectester.reader.command.Command;
-import java.util.Arrays;
+import java.nio.ByteBuffer;
+import java.security.SecureRandom;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -22,13 +24,11 @@ import java.util.Arrays;
public abstract class CardTestSuite extends TestSuite {
ECTesterReader.Config cfg;
CardMngr card;
- String[] options;
- CardTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager, String name, String[] options, String... description) {
+ CardTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager, String name, String... description) {
super(writer, name, description);
this.card = cardManager;
this.cfg = cfg;
- this.options = options;
}
public CardMngr getCard() {
@@ -39,34 +39,16 @@ public abstract class CardTestSuite extends TestSuite {
return cfg;
}
- public String[] getOptions() {
- if (options != null) {
- return options.clone();
- } else {
- return options;
- }
- }
-
- public Test setupKeypairs(EC_Curve curve, Result.ExpectedValue expected, byte keyPair) {
- if ((Arrays.asList(options).contains("preset") && cfg.testOptions.contains("preset")) || (Arrays.asList(options).contains("random") && cfg.testOptions.contains("random"))) {
+ protected Test setupKeypairs(EC_Curve curve, Result.ExpectedValue expected, byte keyPair) {
+ if (cfg.testKeySetup.equals("deterministic") || cfg.testKeySetup.equals("random")) {
Test setLocal = null;
if ((keyPair & CardConsts.KEYPAIR_LOCAL) != 0) {
- EC_Params priv;
- if (cfg.testOptions.contains("preset")) {
- priv = ECUtil.fixedRandomKey(curve);
- } else {
- priv = ECUtil.fullRandomKey(curve);
- }
+ EC_Params priv = preparePrivkey(curve);
setLocal = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_LOCAL, EC_Consts.CURVE_external, priv.getParams(), priv.flatten()), expected);
}
Test setRemote = null;
if ((keyPair & CardConsts.KEYPAIR_REMOTE) != 0) {
- EC_Params pub;
- if (cfg.testOptions.contains("preset")) {
- pub = ECUtil.fixedRandomPoint(curve);
- } else {
- pub = ECUtil.fullRandomPoint(curve);
- }
+ EC_Params pub = preparePubkey(curve);
if (pub == null) {
setRemote = CommandTest.expect(new Command.Generate(this.card, CardConsts.KEYPAIR_REMOTE), expected);
} else {
@@ -80,15 +62,49 @@ public abstract class CardTestSuite extends TestSuite {
return setRemote;
} else {
String desc;
- if (cfg.testOptions.contains("preset")) {
- desc = "Set semi-random parameters.";
+ if (cfg.testKeySetup.equals("deterministic")) {
+ desc = "Set deterministic parameters.";
} else {
desc = "Set fully-random parameters.";
}
- return CompoundTest.all(expected, desc, setLocal, setRemote);
+ return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, setLocal, setRemote);
}
} else {
return CommandTest.expect(new Command.Generate(this.card, keyPair), expected);
}
}
+
+ protected EC_Params preparePrivkey(EC_Curve curve) {
+ if (cfg.testKeySetup.equals("deterministic")) {
+ return ECUtil.fixedRandomKey(curve);
+ } else {
+ return ECUtil.fullRandomKey(curve);
+ }
+ }
+
+ protected EC_Params preparePubkey(EC_Curve curve) {
+ if (cfg.testKeySetup.equals("deterministic")) {
+ return ECUtil.fixedRandomPoint(curve);
+ } else {
+ return ECUtil.fullRandomPoint(curve);
+ }
+ }
+
+ protected SecureRandom setupRandom(EC_Curve curve) {
+ if (cfg.testDataSetup.equals("random")) {
+ return new SecureRandom();
+ } else {
+ return Util.getRandom(ECUtil.hashCurve(curve));
+ }
+ }
+
+ protected SecureRandom setupRandom(int seed) {
+ if (cfg.testDataSetup.equals("random")) {
+ return new SecureRandom();
+ } else {
+ ByteBuffer b = ByteBuffer.allocate(4);
+ b.putInt(seed);
+ return Util.getRandom(b.array());
+ }
+ }
}
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestVectorSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
index 4c222cb..28c5e12 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
@@ -40,7 +40,7 @@ import static cz.crcs.ectester.common.test.Result.Value;
public class CardTestVectorSuite extends CardTestSuite {
public CardTestVectorSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "test-vectors", null, "The test-vectors suite contains a collection of test vectors which test basic ECDH correctness.");
+ super(writer, cfg, cardManager, "test-vectors", "The test-vectors suite contains a collection of test vectors which test basic ECDH correctness.");
}
@Override
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardTwistSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardTwistSuite.java
index ea127e0..6679f60 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardTwistSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardTwistSuite.java
@@ -23,7 +23,7 @@ import java.util.Map;
*/
public class CardTwistSuite extends CardTestSuite {
public CardTwistSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "twist", null, "The twist test suite tests whether the card correctly rejects points on the quadratic twist of the curve during ECDH.");
+ super(writer, cfg, cardManager, "twist", "The twist test suite tests whether the card correctly rejects points on the quadratic twist of the curve during ECDH.");
}
@Override
@@ -36,7 +36,7 @@ public class CardTwistSuite extends CardTestSuite {
Test allocate = CommandTest.expect(new Command.Allocate(this.card, CardConsts.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS);
Test set = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS);
- Test generate = CommandTest.expect(new Command.Generate(this.card, CardConsts.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS);
+ Test generate = setupKeypairs(curve, Result.ExpectedValue.SUCCESS, CardConsts.KEYPAIR_LOCAL);
Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate);
diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardWrongSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardWrongSuite.java
index 605b2ec..f24dabd 100644
--- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardWrongSuite.java
+++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardWrongSuite.java
@@ -30,7 +30,7 @@ import static cz.crcs.ectester.common.test.Result.ExpectedValue;
public class CardWrongSuite extends CardTestSuite {
public CardWrongSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "wrong", new String[]{"preset", "random"}, "The wrong curve suite tests whether the card rejects domain parameters which are not curves.");
+ super(writer, cfg, cardManager, "wrong", "The wrong curve suite tests whether the card rejects domain parameters which are not curves.");
}
@Override
@@ -72,9 +72,9 @@ public class CardWrongSuite extends CardTestSuite {
* - p is a composite q * s with q, s primes
* - TODO: p divides discriminant
*/
- Random r = new Random();
for (short keyLength : EC_Consts.FP_SIZES) {
byte curve = EC_Consts.getCurve(keyLength, EC_Consts.ALG_EC_FP);
+ Random r = setupRandom(curve);
Test key = CommandTest.expect(new Command.Allocate(this.card, CardConsts.KEYPAIR_BOTH, keyLength, EC_Consts.ALG_EC_FP), ExpectedValue.SUCCESS);
Test set = CommandTest.expect(new Command.Set(this.card, CardConsts.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_FP, null), ExpectedValue.SUCCESS);
Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set);
diff --git a/reader/src/test/java/cz/crcs/ectester/reader/OutputTests.java b/reader/src/test/java/cz/crcs/ectester/reader/OutputTests.java
new file mode 100644
index 0000000..5300e98
--- /dev/null
+++ b/reader/src/test/java/cz/crcs/ectester/reader/OutputTests.java
@@ -0,0 +1,13 @@
+package cz.crcs.ectester.reader;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+public class OutputTests {
+
+ @ParameterizedTest
+ @ValueSource(strings = {"text", "xml", "yml"})
+ public void formats(String format) {
+ ECTesterReader.main(new String[]{"-t", "default", "-s", "-o", String.format("%s:out.%s", format, format),});
+ }
+}
diff --git a/standalone/build.gradle.kts b/standalone/build.gradle.kts
index e1fc265..07bf2ab 100644
--- a/standalone/build.gradle.kts
+++ b/standalone/build.gradle.kts
@@ -40,8 +40,8 @@ tasks.named<Test>("test") {
doFirst {
resultsDir.mkdirs();
}
- ignoreFailures = true
useJUnitPlatform()
+
// Report is always generated after tests run
finalizedBy(tasks.named<JacocoReport>("testCodeCoverageReport"))
@@ -52,10 +52,16 @@ tasks.named<Test>("test") {
jvmArgs("--add-exports", "java.base/sun.security.ec=ALL-UNNAMED")
}
+ jvmArgs("-Xmx8G", "-Xms2G")
+
// Add wolfcrypt JNI lib path to LD_LIBRARY_PATH (as our native library loading does not handle it)
environment(
"LD_LIBRARY_PATH", "$rootDir/ext/wolfcrypt-jni/lib/:" + System.getenv("LD_LIBRARY_PATH")
)
+ // Add our preload to tests, so they do not need to start another process.
+ environment(
+ "LD_PRELOAD", "$rootDir/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/lib_preload.so"
+ )
// Add a path where we will store our test results.
environment(
"RESULT_PATH", resultsDir.absolutePath
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 4f76639..04537f0 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -31,6 +31,7 @@ import cz.crcs.ectester.common.test.TestException;
import cz.crcs.ectester.common.util.ByteUtil;
import cz.crcs.ectester.common.util.ECUtil;
import cz.crcs.ectester.common.util.FileUtil;
+import cz.crcs.ectester.common.util.Util;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent;
@@ -104,12 +105,52 @@ public class ECTesterStandalone {
if (!System.getProperty("os.name").startsWith("Windows")) {
FileUtil.write(LIB_RESOURCE_DIR + "lib_timing.so", reqs.resolve("lib_timing.so"));
- System.load(reqs.resolve("lib_timing.so").toString());
-
+ FileUtil.write(LIB_RESOURCE_DIR + "lib_preload.so", reqs.resolve("lib_preload.so"));
+ FileUtil.write(LIB_RESOURCE_DIR + "lib_prng.so", reqs.resolve("lib_prng.so"));
FileUtil.write(LIB_RESOURCE_DIR + "lib_csignals.so", reqs.resolve("lib_csignals.so"));
- System.load(reqs.resolve("lib_csignals.so").toString());
FileUtil.write(LIB_RESOURCE_DIR + "lib_cppsignals.so", reqs.resolve("lib_cppsignals.so"));
- System.load(reqs.resolve("lib_cppsignals.so").toString());
+
+ String preloadLibPath = reqs.resolve("lib_preload.so").toAbsolutePath().toString();
+ String preload = System.getenv("LD_PRELOAD");
+ if (preload == null && !cli.hasOption("no-preload")) {
+ ProcessBuilder builder = new ProcessBuilder();
+ Map<String, String> env = builder.environment();
+ env.put("LD_PRELOAD", preloadLibPath);
+
+ ProcessHandle.Info info = ProcessHandle.current().info();
+ List<String> argList = new LinkedList<>();
+ if (info.command().isPresent()) {
+ argList.add(info.command().get());
+ } else {
+ System.err.println("Cannot locate command to spawn preloaded-subprocess.");
+ return;
+ }
+ if (info.arguments().isPresent()) {
+ argList.addAll(List.of(info.arguments().get()));
+ } else {
+ System.err.println("Cannot locate arguments to spawn preloaded-subprocess.");
+ return;
+ }
+ builder.command(argList);
+ builder.inheritIO();
+
+ Process process = builder.start();
+ int result;
+ while (true) {
+ try {
+ result = process.waitFor();
+ break;
+ } catch (InterruptedException ignored) {
+ }
+ }
+ System.exit(result);
+ } else {
+ // Load the utility libs.
+ System.load(reqs.resolve("lib_prng.so").toString());
+ System.load(reqs.resolve("lib_timing.so").toString());
+ System.load(reqs.resolve("lib_csignals.so").toString());
+ System.load(reqs.resolve("lib_cppsignals.so").toString());
+ }
}
List<ProviderECLibrary> libObjects = new LinkedList<>();
@@ -191,7 +232,15 @@ public class ECTesterStandalone {
Option output = Option.builder("o").longOpt("output").desc("Output into file <output_file>. The file can be prefixed by the format (one of text,yml,xml), such as: xml:<output_file>.").hasArgs().argName("output_file").optionalArg(false).numberOfArgs(1).build();
Option outputRaw = Option.builder("o").longOpt("output").desc("Output CSV into file <output_file>.").hasArgs().argName("output_file").optionalArg(false).numberOfArgs(1).build();
Option quiet = Option.builder("q").longOpt("quiet").desc("Do not output to stdout.").build();
- Option timeSource = Option.builder("ts").longOpt("time-source").desc("Use a given native timing source: {rdtsc, monotonic, monotonic-raw, cputime-process, cputime-thread, perfcount}").hasArgs().argName("source").optionalArg(false).numberOfArgs(1).build();
+ Option timeSource = Option.builder("ts").longOpt("time-source").desc("Use a given native timing source: {rdtsc, monotonic, monotonic-raw, cputime-process, cputime-thread}").hasArgs().argName("source").optionalArg(false).numberOfArgs(1).build();
+ Option prngSeed = Option.builder("ps").longOpt("prng-seed").desc("Use a deterministic PRNG with the given [seed] (hexadecimal) in the library.").hasArgs().argName("seed").optionalArg(false).numberOfArgs(1).build();
+ Option file = Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build();
+ Option message = Option.builder("d").longOpt("data").desc("Sign the given [message].").hasArgs().argName("message").optionalArg(false).numberOfArgs(1).build();
+ Option messageSeed = Option.builder("ds").longOpt("data-seed").desc("Use a deterministic PRNG with the given [seed] (hexadecimal) to generate the messages.").hasArgs().argName("seed").optionalArg(false).numberOfArgs(1).build();
+ OptionGroup ecdsaMessage = new OptionGroup();
+ ecdsaMessage.addOption(file);
+ ecdsaMessage.addOption(message);
+ ecdsaMessage.addOption(messageSeed);
Options testOpts = new Options();
testOpts.addOption(bits);
@@ -199,6 +248,7 @@ public class ECTesterStandalone {
testOpts.addOption(curveName);
testOpts.addOption(output);
testOpts.addOption(quiet);
+ testOpts.addOption(prngSeed);
testOpts.addOption(Option.builder("gt").longOpt("kpg-type").desc("Set the KeyPairGenerator object [type].").hasArg().argName("type").optionalArg(false).build());
testOpts.addOption(Option.builder("kt").longOpt("ka-type").desc("Set the KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build());
testOpts.addOption(Option.builder("st").longOpt("sig-type").desc("Set the Signature object [type].").hasArg().argName("type").optionalArg(false).build());
@@ -215,6 +265,7 @@ public class ECTesterStandalone {
ecdhOpts.addOption(curveName);
ecdhOpts.addOption(outputRaw);
ecdhOpts.addOption(timeSource);
+ ecdhOpts.addOption(prngSeed);
ecdhOpts.addOption(Option.builder("t").longOpt("type").desc("Set KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build());
ecdhOpts.addOption(Option.builder().longOpt("key-type").desc("Set the key [algorithm] for which the key should be derived in KeyAgreements with KDF. Default is \"AES\".").hasArg().argName("algorithm").optionalArg(false).build());
ecdhOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDH [amount] times.").build());
@@ -231,12 +282,13 @@ public class ECTesterStandalone {
ecdsaOpts.addOption(curveName);
ecdsaOpts.addOption(outputRaw);
ecdsaOpts.addOption(timeSource);
+ ecdsaOpts.addOption(prngSeed);
ecdsaOpts.addOptionGroup(privateKey);
ecdsaOpts.addOptionGroup(publicKey);
ecdsaOpts.addOption(Option.builder().longOpt("fixed").desc("Perform all ECDSA with fixed keypair.").build());
ecdsaOpts.addOption(Option.builder("t").longOpt("type").desc("Set Signature object [type].").hasArg().argName("type").optionalArg(false).build());
ecdsaOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDSA [amount] times.").build());
- ecdsaOpts.addOption(Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build());
+ ecdsaOpts.addOptionGroup(ecdsaMessage);
ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts, "Perform EC based Signature.");
actions.put("ecdsa", ecdsa);
@@ -246,6 +298,7 @@ public class ECTesterStandalone {
generateOpts.addOption(curveName);
generateOpts.addOption(outputRaw);
generateOpts.addOption(timeSource);
+ generateOpts.addOption(prngSeed);
generateOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Generate [amount] of EC keys.").build());
generateOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPairGenerator object [type].").build());
ParserOptions generate = new ParserOptions(new DefaultParser(), generateOpts, "Generate EC keypairs.");
@@ -283,6 +336,7 @@ public class ECTesterStandalone {
opts.addOption(Option.builder("V").longOpt("version").desc("Print version info.").build());
opts.addOption(Option.builder("h").longOpt("help").desc("Print help(about <command>).").hasArg().argName("command").optionalArg(true).build());
opts.addOption(Option.builder("C").longOpt("color").desc("Print stuff with color, requires ANSI terminal.").build());
+ opts.addOption(Option.builder().longOpt("no-preload").desc("Do not use LD_PRELOAD.").build());
return optParser.parse(opts, args);
}
@@ -307,6 +361,7 @@ public class ECTesterStandalone {
System.out.println(Colors.bold("\t\t- Fullname: ") + lib.getProvider().getName());
System.out.println(Colors.bold("\t\t- Version: ") + lib.getProvider().getVersionStr());
System.out.println(Colors.bold("\t\t- Supports native timing: ") + lib.getNativeTimingSupport().toString());
+ System.out.println(Colors.bold("\t\t- Supports deterministic PRNG: ") + lib.supportsDeterministicPRNG());
Set<KeyPairGeneratorIdent> kpgs = lib.getKPGs();
if (!kpgs.isEmpty()) {
System.out.println(Colors.bold("\t\t- KeyPairGenerators: ") + kpgs.stream().map(KeyPairGeneratorIdent::getName).sorted().collect(Collectors.joining(", ")));
@@ -409,12 +464,25 @@ public class ECTesterStandalone {
throw new NoSuchAlgorithmException(algo);
}
+ SecureRandom random;
+ if (cli.hasOption("ecdh.prng-seed")) {
+ String seedString = cli.getOptionValue("ecdh.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ random = Util.getRandom(seed);
+ if (!lib.setupDeterministicPRNG(seed)) {
+ System.err.println("Couldn't set PRNG seed.");
+ return;
+ }
+ } else {
+ random = new SecureRandom();
+ }
+
KeyAgreement ka = kaIdent.getInstance(lib.getProvider());
KeyPairGenerator kpg = kpIdent.getInstance(lib.getProvider());
AlgorithmParameterSpec spec = null;
if (cli.hasOption("ecdh.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("ecdh.bits"));
- kpg.initialize(bits);
+ kpg.initialize(bits, random);
} else if (cli.hasOption("ecdh.named-curve")) {
String curveName = cli.getOptionValue("ecdh.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -423,11 +491,15 @@ public class ECTesterStandalone {
return;
}
spec = curve.toSpec();
- kpg.initialize(spec);
+ kpg.initialize(spec, random);
} else if (cli.hasOption("ecdh.curve-name")) {
String curveName = cli.getOptionValue("ecdh.curve-name");
spec = new ECGenParameterSpec(curveName);
- kpg.initialize(spec);
+ kpg.initialize(spec, random);
+ } else if (cli.hasOption("ecdh.prng-seed") && !(lib instanceof NativeECLibrary)) {
+ // TODO: This only happens if at least one of the (pubkey and privkey) needs to be generated.
+ System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options.");
+ return;
}
if (cli.hasOption("ecdh.time-source")) {
@@ -483,9 +555,9 @@ public class ECTesterStandalone {
long elapsed = -System.nanoTime();
if (spec instanceof ECParameterSpec && lib instanceof NativeECLibrary) {
- ka.init(privkey, spec);
+ ka.init(privkey, spec, random);
} else {
- ka.init(privkey);
+ ka.init(privkey, random);
}
ka.doPhase(pubkey, true);
elapsed += System.nanoTime();
@@ -519,8 +591,24 @@ public class ECTesterStandalone {
*
*/
private void ecdsa() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException, SignatureException {
- byte[] data;
- String dataString;
+ ProviderECLibrary lib = cfg.selected;
+
+ SecureRandom random;
+ if (cli.hasOption("ecdsa.prng-seed")) {
+ String seedString = cli.getOptionValue("ecdsa.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ random = Util.getRandom(seed);
+ if (!lib.setupDeterministicPRNG(seed)) {
+ System.err.println("Couldn't set PRNG seed.");
+ return;
+ }
+ } else {
+ random = new SecureRandom();
+ }
+
+ byte[] data = null;
+ String dataString = null;
+ SecureRandom dataRandom = null;
if (cli.hasOption("ecdsa.file")) {
String fileName = cli.getOptionValue("ecdsa.file");
File in = new File(fileName);
@@ -530,13 +618,17 @@ public class ECTesterStandalone {
}
data = Files.readAllBytes(in.toPath());
dataString = "";
+ } else if (cli.hasOption("ecdsa.data")) {
+ dataString = cli.getOptionValue("ecdsa.data");
+ data = ByteUtil.hexToBytes(dataString);
+ } else if (cli.hasOption("ecdsa.data-seed")) {
+ String seedString = cli.getOptionValue("ecdsa.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ dataRandom = Util.getRandom(seed);
} else {
- Random random = new Random();
- data = new byte[32];
- random.nextBytes(data);
- dataString = ByteUtil.bytesToHex(data, false);
+ dataRandom = new SecureRandom();
}
- ProviderECLibrary lib = cfg.selected;
+
String algo = cli.getOptionValue("ecdsa.type", "ECDSA");
SignatureIdent sigIdent = lib.getSigs().stream()
.filter((ident) -> ident.contains(algo))
@@ -571,7 +663,7 @@ public class ECTesterStandalone {
ECParameterSpec spec = null;
if (cli.hasOption("ecdsa.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("ecdsa.bits"));
- kpg.initialize(bits);
+ kpg.initialize(bits, random);
} else if (cli.hasOption("ecdsa.named-curve")) {
String curveName = cli.getOptionValue("ecdsa.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -580,10 +672,14 @@ public class ECTesterStandalone {
return;
}
spec = curve.toSpec();
- kpg.initialize(spec);
+ kpg.initialize(spec, random);
} else if (cli.hasOption("ecdsa.curve-name")) {
String curveName = cli.getOptionValue("ecdsa.curve-name");
- kpg.initialize(new ECGenParameterSpec(curveName));
+ kpg.initialize(new ECGenParameterSpec(curveName), random);
+ } else if (cli.hasOption("ecdsa.prng-seed") && !(lib instanceof NativeECLibrary)) {
+ // TODO: This only happens if at least one of the (pubkey and privkey) needs to be generated.
+ System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options.");
+ return;
}
if (cli.hasOption("ecdsa.time-source")) {
@@ -636,7 +732,12 @@ public class ECTesterStandalone {
}
}
- sig.initSign(privkey);
+ if (dataRandom != null) {
+ data = dataRandom.generateSeed(16);
+ dataString = ByteUtil.bytesToHex(data, false);
+ }
+
+ sig.initSign(privkey, random);
sig.update(data);
long signTime = -System.nanoTime();
@@ -705,10 +806,24 @@ public class ECTesterStandalone {
if (ident == null) {
throw new NoSuchAlgorithmException(algo);
}
+
+ SecureRandom random;
+ if (cli.hasOption("generate.prng-seed")) {
+ String seedString = cli.getOptionValue("generate.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ random = Util.getRandom(seed);
+ if (!lib.setupDeterministicPRNG(seed)) {
+ System.err.println("Couldn't set PRNG seed.");
+ return;
+ }
+ } else {
+ random = new SecureRandom();
+ }
+
KeyPairGenerator kpg = ident.getInstance(lib.getProvider());
if (cli.hasOption("generate.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("generate.bits"));
- kpg.initialize(bits);
+ kpg.initialize(bits, random);
} else if (cli.hasOption("generate.named-curve")) {
String curveName = cli.getOptionValue("generate.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -716,10 +831,13 @@ public class ECTesterStandalone {
System.err.println("Curve not found: " + curveName);
return;
}
- kpg.initialize(curve.toSpec());
+ kpg.initialize(curve.toSpec(), random);
} else if (cli.hasOption("generate.curve-name")) {
String curveName = cli.getOptionValue("generate.curve-name");
- kpg.initialize(new ECGenParameterSpec(curveName));
+ kpg.initialize(new ECGenParameterSpec(curveName), random);
+ } else if (cli.hasOption("generate.prng-seed") && !(lib instanceof NativeECLibrary)) {
+ System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options.");
+ return;
}
if (cli.hasOption("generate.time-source")) {
@@ -818,6 +936,16 @@ public class ECTesterStandalone {
testTo = -1;
}
+ ProviderECLibrary lib = cfg.selected;
+ if (cli.hasOption("test.prng-seed")) {
+ String seedString = cli.getOptionValue("test.prng-seed");
+ byte[] seed = ByteUtil.hexToBytes(seedString, true);
+ if (!lib.setupDeterministicPRNG(seed)) {
+ System.err.println("Couldn't set PRNG seed.");
+ return;
+ }
+ }
+
switch (testSuite) {
case "test-vectors":
suite = new StandaloneTestVectorSuite(writer, cfg, cli);
@@ -997,6 +1125,15 @@ public class ECTesterStandalone {
}
}
+ if (cli.isNext("generate") || cli.isNext("ecdh") || cli.isNext("ecdsa") || cli.isNext("test")) {
+ if (cli.hasOption(next + ".prng-seed")) {
+ if (!selected.supportsDeterministicPRNG()) {
+ System.err.printf("Deterministic PRNG is not supported by library %s.%n", selected.name());
+ return false;
+ }
+ }
+ }
+
return true;
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java
index af4d969..06e6b4a 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java
@@ -16,4 +16,10 @@ public class BoringsslLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ // This is provided by the native preload that hooks all randomness sources.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java
index e8f6e13..c072e84 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java
@@ -17,4 +17,10 @@ public class BotanLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java
index e8a4d30..0a7ea8c 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java
@@ -25,4 +25,16 @@ public class BouncyCastleLib extends ProviderECLibrary {
}
return result;
}
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ return true;
+ }
+
+ @Override
+ public boolean setupDeterministicPRNG(byte[] seed) {
+ // This is done by passing the SecureRandom into the individual KeyPairGenerator, KeyAgreement and Signature
+ // instances. Thus, this does nothing.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java
index 66aa9ea..25f2de4 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java
@@ -17,4 +17,10 @@ public class CryptoppLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java
index 83d78ef..d1452a9 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java
@@ -17,4 +17,10 @@ public class GcryptLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ // This is provided by the native preload that hooks all randomness sources.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java
index 115fe00..fa51585 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java
@@ -17,4 +17,10 @@ public class IppcpLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java
index 2dba049..e53399c 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java
@@ -16,4 +16,10 @@ public class LibresslLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ // This is provided by the native preload that hooks all randomness sources.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
index e44598c..efc8cad 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
@@ -17,4 +17,10 @@ public class MbedTLSLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
index c11dbdb..fb4e430 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
@@ -86,5 +86,8 @@ public abstract class NativeECLibrary extends ProviderECLibrary {
@Override
public native long getLastNativeTiming();
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
+
abstract Provider createProvider();
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java
index d4df414..aa90c38 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java
@@ -49,4 +49,10 @@ public class NettleLib extends NativeECLibrary {
}
throw new InvalidAlgorithmParameterException("Unknown curve.");
}
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java
index 61f00a4..69c84bc 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java
@@ -16,4 +16,10 @@ public class OpensslLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
index d9d6749..a9178f6 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
@@ -69,21 +69,29 @@ public abstract class ProviderECLibrary implements ECLibrary {
}
public boolean setNativeTimingType(String type) {
- return false;
+ return false;
}
public long getNativeTimingResolution() {
return 0;
}
- public String getNativeTimingUnit() {
- return null;
- }
+ public String getNativeTimingUnit() {
+ return null;
+ }
public long getLastNativeTiming() {
return 0;
}
+ public boolean supportsDeterministicPRNG() {
+ return false;
+ }
+
+ public boolean setupDeterministicPRNG(byte[] seed) {
+ return false;
+ }
+
@Override
public Set<KeyAgreementIdent> getKAs() {
return getIdents("KeyAgreement", KeyAgreementIdent::get);
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java
index 7209dc3..c38300d 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java
@@ -25,4 +25,16 @@ public class SunECLib extends ProviderECLibrary {
}
return result;
}
+
+ @Override
+ public boolean supportsDeterministicPRNG() {
+ return true;
+ }
+
+ @Override
+ public boolean setupDeterministicPRNG(byte[] seed) {
+ // This is done by passing the SecureRandom into the individual KeyPairGenerator, KeyAgreement and Signature
+ // instances. Thus, this does nothing.
+ return true;
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java
index 8c000a2..e499451 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java
@@ -17,4 +17,10 @@ public class TomcryptLib extends NativeECLibrary {
@Override
public native Set<String> getCurves();
+
+ @Override
+ public native boolean supportsDeterministicPRNG();
+
+ @Override
+ public native boolean setupDeterministicPRNG(byte[] seed);
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java b/standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java
index 13a9e72..c3ddea5 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/output/TextTestWriter.java
@@ -4,6 +4,7 @@ import cz.crcs.ectester.common.cli.Colors;
import cz.crcs.ectester.common.output.BaseTextTestWriter;
import cz.crcs.ectester.common.test.TestSuite;
import cz.crcs.ectester.common.test.Testable;
+import cz.crcs.ectester.common.util.ByteUtil;
import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.test.base.StandaloneTestable;
import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
@@ -47,7 +48,8 @@ public class TextTestWriter extends BaseTextTestWriter {
if (suite instanceof StandaloneTestSuite) {
StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite;
String sb = "═══ " + Colors.underline("ECTester version:") + " " + ECTesterStandalone.VERSION + System.lineSeparator() +
- "═══ " + Colors.underline("Library:") + " " + standaloneSuite.getLibrary().fullName() + System.lineSeparator();
+ "═══ " + Colors.underline("Library:") + " " + standaloneSuite.getLibrary().fullName() + System.lineSeparator() +
+ "═══ " + Colors.underline("Seed:") + " " + ByteUtil.bytesToHex(standaloneSuite.getSeed()) + System.lineSeparator();
return sb;
}
return "";
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java b/standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java
index 2341fc7..06e7399 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/output/XMLTestWriter.java
@@ -149,6 +149,10 @@ public class XMLTestWriter extends BaseXMLTestWriter {
Element name = doc.createElement("name");
name.setTextContent(standaloneSuite.getLibrary().fullName());
result.appendChild(name);
+
+ Element seed = doc.createElement("seed");
+ seed.setTextContent(ByteUtil.bytesToHex(standaloneSuite.getSeed()));
+ result.appendChild(seed);
return result;
}
return null;
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java b/standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
index 66c5e38..d22c441 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
@@ -117,6 +117,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
result.put("type", "library");
result.put("ectester", ECTesterStandalone.VERSION);
result.put("name", standaloneSuite.getLibrary().fullName());
+ result.put("seed", ByteUtil.bytesToHex(standaloneSuite.getSeed()));
return result;
}
return null;
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
index 579904c..6566a9c 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
@@ -5,6 +5,7 @@ import javax.crypto.SecretKey;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
@@ -17,94 +18,24 @@ public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestabl
private KeyAgreement ka;
private ECPrivateKey privateKey;
private ECPublicKey publicKey;
- private KeyGeneratorTestable kgtPrivate;
- private KeyGeneratorTestable kgtPublic;
- private AlgorithmParameterSpec spec;
- private String keyAlgo;
+ private final KeyGeneratorTestable kgtPrivate;
+ private final KeyGeneratorTestable kgtPublic;
+ private final AlgorithmParameterSpec spec;
+ private final String keyAlgo;
+ private final SecureRandom random;
+
private byte[] secret;
private SecretKey derived;
- public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey) {
- this.ka = ka;
- this.privateKey = privateKey;
- this.publicKey = publicKey;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, String keyAlgo) {
- this(ka, privateKey, publicKey);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, ECParameterSpec spec) {
- this(ka, privateKey, publicKey);
- this.spec = spec;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, ECParameterSpec spec, String keyAlgo) {
- this(ka, privateKey, publicKey, spec);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, ECParameterSpec spec) {
- this(ka, privateKey, null, spec);
- this.kgtPublic = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, ECParameterSpec spec, String keyAlgo) {
- this(ka, kgt, privateKey, spec);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, ECParameterSpec spec) {
- this(ka, null, publicKey, spec);
- this.kgtPrivate = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, ECParameterSpec spec, String keyAlgo) {
- this(ka, publicKey, kgt, spec);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, ECParameterSpec spec) {
- this(ka, null, (ECPublicKey) null, spec);
- this.kgtPrivate = privKgt;
- this.kgtPublic = pubKgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, ECParameterSpec spec, String keyAlgo) {
- this(ka, privKgt, pubKgt, spec);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey) {
- this(ka, privateKey, null, (ECParameterSpec) null);
- this.kgtPublic = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, String keyAlgo) {
- this(ka, kgt, privateKey, (ECParameterSpec) null);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt) {
- this(ka, null, publicKey, (ECParameterSpec) null);
- this.kgtPrivate = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, String keyAlgo) {
- this(ka, publicKey, kgt, (ECParameterSpec) null);
- this.keyAlgo = keyAlgo;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt) {
- this(ka, null, (ECPublicKey) null, (ECParameterSpec) null);
- this.kgtPrivate = privKgt;
- this.kgtPublic = pubKgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, String keyAlgo) {
- this(ka, privKgt, pubKgt, (ECParameterSpec) null);
- this.keyAlgo = keyAlgo;
+ KeyAgreementTestable(Builder builder) {
+ this.ka = builder.ka;
+ this.privateKey = builder.privateKey;
+ this.publicKey = builder.publicKey;
+ this.kgtPrivate = builder.kgtPrivate;
+ this.kgtPublic = builder.kgtPublic;
+ this.spec = builder.spec;
+ this.keyAlgo = builder.keyAlgo;
+ this.random = builder.random;
}
public String getKeyAlgorithm() {
@@ -153,9 +84,17 @@ public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestabl
stage = KeyAgreementStage.Init;
try {
if (spec != null) {
- ka.init(privateKey, spec);
+ if (random != null) {
+ ka.init(privateKey, spec, random);
+ } else {
+ ka.init(privateKey, spec);
+ }
} else {
- ka.init(privateKey);
+ if (random != null) {
+ ka.init(privateKey, random);
+ } else {
+ ka.init(privateKey);
+ }
}
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
failOnException(e);
@@ -197,7 +136,12 @@ public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestabl
super.reset();
try {
ka = KeyAgreement.getInstance(ka.getAlgorithm(), ka.getProvider());
- } catch (NoSuchAlgorithmException e) { }
+ } catch (NoSuchAlgorithmException e) {
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
}
public enum KeyAgreementStage {
@@ -207,4 +151,68 @@ public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestabl
DoPhase,
GenerateSecret
}
+
+ public static class Builder {
+ private KeyAgreement ka;
+ private ECPrivateKey privateKey;
+ private ECPublicKey publicKey;
+ private KeyGeneratorTestable kgtPrivate;
+ private KeyGeneratorTestable kgtPublic;
+ private AlgorithmParameterSpec spec;
+ private String keyAlgo;
+ private SecureRandom random;
+
+ public Builder ka(KeyAgreement ka) {
+ this.ka = ka;
+ return this;
+ }
+
+ public Builder privateKey(ECPrivateKey privateKey) {
+ this.privateKey = privateKey;
+ return this;
+ }
+
+ public Builder publicKey(ECPublicKey publicKey) {
+ this.publicKey = publicKey;
+ return this;
+ }
+
+ public Builder privateKgt(KeyGeneratorTestable privateKgt) {
+ this.kgtPrivate = privateKgt;
+ return this;
+ }
+
+ public Builder publicKgt(KeyGeneratorTestable publicKgt) {
+ this.kgtPublic = publicKgt;
+ return this;
+ }
+
+ public Builder spec(AlgorithmParameterSpec spec) {
+ this.spec = spec;
+ return this;
+ }
+
+ public Builder keyAlgo(String keyAlgo) {
+ this.keyAlgo = keyAlgo;
+ return this;
+ }
+
+ public Builder random(SecureRandom random) {
+ this.random = random;
+ return this;
+ }
+
+ public KeyAgreementTestable build() {
+ if (ka == null) {
+ throw new NullPointerException("ka needs to be non-null.");
+ }
+ if ((privateKey == null) == (kgtPrivate == null)) {
+ throw new IllegalStateException("One of (but not both) privateKey or privateKgt needs to be non-null.");
+ }
+ if ((publicKey == null) == (kgtPublic == null)) {
+ throw new IllegalStateException("One of (but not both) publicKey or publicKgt needs to be non-null.");
+ }
+ return new KeyAgreementTestable(this);
+ }
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
index bc44eb8..f9c84e1 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
@@ -3,6 +3,7 @@ package cz.crcs.ectester.standalone.test.base;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
+import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
@@ -15,24 +16,17 @@ public class KeyGeneratorTestable extends StandaloneTestable<KeyGeneratorTestabl
private final KeyPairGenerator kpg;
private int keysize = 0;
private AlgorithmParameterSpec spec = null;
+ private SecureRandom random;
public KeyGeneratorTestable(KeyPairGenerator kpg) {
this.kpg = kpg;
}
- public KeyGeneratorTestable(KeyPairGenerator kpg, int keysize) {
- this.kpg = kpg;
- this.keysize = keysize;
- }
-
- public KeyGeneratorTestable(KeyPairGenerator kpg, ECParameterSpec spec) {
- this.kpg = kpg;
- this.spec = spec;
- }
-
- public KeyGeneratorTestable(KeyPairGenerator kpg, ECGenParameterSpec spec) {
- this.kpg = kpg;
- this.spec = spec;
+ KeyGeneratorTestable(Builder builder) {
+ this.kpg = builder.kpg;
+ this.keysize = builder.keysize;
+ this.spec = builder.spec;
+ this.random = builder.random;
}
public int getKeysize() {
@@ -57,9 +51,17 @@ public class KeyGeneratorTestable extends StandaloneTestable<KeyGeneratorTestabl
stage = KeyGeneratorStage.Init;
try {
if (spec != null) {
- kpg.initialize(spec);
+ if (random != null) {
+ kpg.initialize(spec, random);
+ } else {
+ kpg.initialize(spec);
+ }
} else if (keysize != 0) {
- kpg.initialize(keysize);
+ if (random != null) {
+ kpg.initialize(keysize, random);
+ } else {
+ kpg.initialize(keysize);
+ }
}
} catch (InvalidAlgorithmParameterException e) {
failOnException(e);
@@ -78,8 +80,56 @@ public class KeyGeneratorTestable extends StandaloneTestable<KeyGeneratorTestabl
hasRun = true;
}
+ public static Builder builder() {
+ return new Builder();
+ }
+
public enum KeyGeneratorStage {
Init,
GenKeyPair
}
+
+ public static class Builder {
+ private KeyPairGenerator kpg;
+ private int keysize = 0;
+ private AlgorithmParameterSpec spec = null;
+ private SecureRandom random;
+
+ public Builder() {}
+
+ public Builder keyPairGenerator(KeyPairGenerator kpg) {
+ this.kpg = kpg;
+ return this;
+ }
+
+ public Builder keysize(int keysize) {
+ this.keysize = keysize;
+ return this;
+ }
+
+ public Builder spec(ECGenParameterSpec spec) {
+ this.spec = spec;
+ return this;
+ }
+
+ public Builder spec(ECParameterSpec spec) {
+ this.spec = spec;
+ return this;
+ }
+
+ public Builder random(SecureRandom random) {
+ this.random = random;
+ return this;
+ }
+
+ public KeyGeneratorTestable build() {
+ if (kpg == null) {
+ throw new NullPointerException("kpg mus be non-null.");
+ }
+ if (spec != null && keysize != 0) {
+ throw new IllegalStateException("Only one of spec and keysize can be set.");
+ }
+ return new KeyGeneratorTestable(this);
+ }
+ }
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
index 76074e4..5839497 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
@@ -15,32 +15,32 @@ public class SignatureTestable extends StandaloneTestable<SignatureTestable.Sign
private ECPrivateKey signKey;
private ECPublicKey verifyKey;
private KeyGeneratorTestable kgt;
+ private SecureRandom random;
private byte[] data;
private byte[] signature;
private boolean verified;
- public SignatureTestable(Signature sig, ECPrivateKey signKey, ECPublicKey verifyKey, byte[] data) {
+ public SignatureTestable(Signature sig, ECPrivateKey signKey, ECPublicKey verifyKey, byte[] data, SecureRandom random) {
this.sig = sig;
this.signKey = signKey;
this.verifyKey = verifyKey;
this.data = data;
- if (data == null) {
- SecureRandom random = new SecureRandom();
- this.data = new byte[64];
- random.nextBytes(this.data);
- }
+ this.random = random;
}
- public SignatureTestable(Signature sig, ECPublicKey verifyKey, byte[] data, byte[] signature) {
+ public SignatureTestable(Signature sig, ECPublicKey verifyKey, byte[] data, byte[] signature, SecureRandom random) {
this.sig = sig;
this.verifyKey = verifyKey;
this.data = data;
this.signature = signature;
+ this.random = random;
}
- public SignatureTestable(Signature sig, KeyGeneratorTestable kgt, byte[] data) {
- this(sig, (ECPrivateKey) null, null, data);
+ public SignatureTestable(Signature sig, KeyGeneratorTestable kgt, byte[] data, SecureRandom random) {
+ this.sig = sig;
this.kgt = kgt;
+ this.data = data;
+ this.random = random;
}
public Signature getSig() {
@@ -71,7 +71,11 @@ public class SignatureTestable extends StandaloneTestable<SignatureTestable.Sign
if(signKey != null) {
stage = SignatureStage.InitSign;
try {
- sig.initSign(signKey);
+ if (random != null) {
+ sig.initSign(signKey, random);
+ } else {
+ sig.initSign(signKey);
+ }
} catch (InvalidKeyException e) {
failOnException(e);
return;
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java
index 003d510..5079770 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java
@@ -56,7 +56,7 @@ public class StandaloneCofactorSuite extends StandaloneTestSuite {
KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider());
ECParameterSpec spec = curve.toSpec();
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
@@ -67,7 +67,7 @@ public class StandaloneCofactorSuite extends StandaloneTestSuite {
for (EC_Key.Public pub : keys) {
ECPublicKey ecpub = ECUtil.toPublicKey(pub);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpub, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(kgt).random(getRandom()).build();
Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE);
specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " cofactor key test.", keyAgreement));
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java
index 38d76bc..d838d20 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneCompositeSuite.java
@@ -64,7 +64,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
ECParameterSpec spec = curve.toSpec();
//Generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//Perform KeyAgreement tests
@@ -75,7 +75,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
for (EC_Key.Public pub : curveKeys.getValue()) {
ECPublicKey ecpub = ECUtil.toPublicKey(pub);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpub, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(kgt).random(getRandom()).build();
Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE);
specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", with generated private key, " + pub.getDesc(), keyAgreement));
}
@@ -133,7 +133,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
}
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, curve.toSpec());
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(curve.toSpec()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//perform KeyAgreement tests
@@ -141,7 +141,7 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) {
if (kaAlgo == null || kaIdent.containsAny(kaTypes)) {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKgt(kgt).privateKgt(kgt).random(getRandom()).build();
kaTests.add(KeyAgreementTest.expectError(testable, dhValue));
}
}
@@ -154,7 +154,8 @@ public class StandaloneCompositeSuite extends StandaloneTestSuite {
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
if (sigAlgo == null || sigIdent.containsAny(sigTypes)) {
Signature sig = sigIdent.getInstance(cfg.selected.getProvider());
- SignatureTestable testable = new SignatureTestable(sig, kgt, null);
+ byte[] data = sigIdent.toString().getBytes();
+ SignatureTestable testable = new SignatureTestable(sig, kgt, data, getRandom());
sigTests.add(SignatureTest.expectError(testable, dhValue));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
index ef9d434..a9b82d5 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
@@ -4,6 +4,7 @@ import cz.crcs.ectester.common.cli.TreeCommandLine;
import cz.crcs.ectester.common.ec.EC_Curve;
import cz.crcs.ectester.common.output.TestWriter;
import cz.crcs.ectester.common.test.Result;
+import cz.crcs.ectester.common.util.ECUtil;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
@@ -44,8 +45,8 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
ECParameterSpec spec = null;
if (cli.hasOption("test.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("test.bits"));
- kgtOne = new KeyGeneratorTestable(kpg, bits);
- kgtOther = new KeyGeneratorTestable(kpg, bits);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).keysize(bits).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).keysize(bits).build();
} else if (cli.hasOption("test.named-curve")) {
String curveName = cli.getOptionValue("test.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -54,11 +55,11 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
return;
}
spec = curve.toSpec();
- kgtOne = new KeyGeneratorTestable(kpg, spec);
- kgtOther = new KeyGeneratorTestable(kpg, spec);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(spec).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(spec).build();
} else {
- kgtOne = new KeyGeneratorTestable(kpg);
- kgtOther = new KeyGeneratorTestable(kpg);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build();
}
doTest(KeyGeneratorTest.expect(kgtOne, Result.ExpectedValue.SUCCESS));
@@ -69,9 +70,9 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
KeyAgreementTestable testable;
if (kaIdent.requiresKeyAlgo()) {
- testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec, keyAlgo);
+ testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).keyAlgo(keyAlgo).build();
} else {
- testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec);
+ testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).build();
}
doTest(KeyAgreementTest.expect(testable, Result.ExpectedValue.SUCCESS));
}
@@ -79,7 +80,8 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
if (sigAlgo == null || sigIdent.contains(sigAlgo)) {
Signature sig = sigIdent.getInstance(cfg.selected.getProvider());
- doTest(SignatureTest.expect(new SignatureTestable(sig, kgtOne, null), Result.ExpectedValue.SUCCESS));
+ byte[] data = sigIdent.toString().getBytes();
+ doTest(SignatureTest.expect(new SignatureTestable(sig, kgtOne, data, getRandom()), Result.ExpectedValue.SUCCESS));
}
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java
index d441235..12a9f16 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java
@@ -92,7 +92,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
ECPublicKey ecpub = ECUtil.toPublicKey(EC_Store.getInstance().getObject(EC_Key.Public.class, pubkeyId));
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(ecpriv).publicKey(ecpub).random(getRandom()).build();
Test ecdh = KeyAgreementTest.match(testable, value.getData(0));
Test one = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test " + id + ".", ecdh);
curveTests.add(one);
@@ -107,7 +107,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
ECPrivateKey ecpriv = ECUtil.toPrivateKey(EC_Store.getInstance().getObject(EC_Key.Private.class, openssl_bug.getOtherKey()));
ECPublicKey ecpub = ECUtil.toPublicKey(EC_Store.getInstance().getObject(EC_Key.Public.class, openssl_bug.getOneKey()));
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(ecpriv).publicKey(ecpub).random(getRandom()).build();
Test ecdh = KeyAgreementTest.function(testable, new TestCallback<KeyAgreementTestable>() {
@Override
public Result apply(KeyAgreementTestable testable) {
@@ -129,12 +129,12 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
e.getKey().endsWith("r1") && e.getValue().getField() == javacard.security.KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList());
curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor128p2"));
curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor160p4"));
- Random rand = new Random();
+ Random rand = getRandom();
for (EC_Curve curve : curves) {
ECParameterSpec spec = curve.toSpec();
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//perform ECDH tests
@@ -213,7 +213,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
Arrays.sort(zeros);
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//perform ECDH tests
@@ -247,7 +247,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite {
private Test ecdhTest(KeyGeneratorTestable kgt, BigInteger SParam, ECParameterSpec spec, String desc, Result.ExpectedValue expect) throws NoSuchAlgorithmException {
ECPrivateKey priv = new RawECPrivateKey(SParam, spec);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, priv);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(priv).publicKgt(kgt).random(getRandom()).build();
return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, KeyAgreementTest.expectError(testable, expect));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java
index 21431ae..da5d19a 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java
@@ -57,9 +57,9 @@ public abstract class StandaloneForeignSuite extends StandaloneTestSuite {
ECParameterSpec spec = curve.toSpec();
ECGenParameterSpec namedSpec = new ECGenParameterSpec(curve.getId());
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
- KeyGeneratorTestable kgtOnNamedCurve = new KeyGeneratorTestable(kpg, namedSpec);
- KeyGeneratorTestable kgtOnDefaultCurve = new KeyGeneratorTestable(kpg, curve.getBits());
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(spec).build();
+ KeyGeneratorTestable kgtOnNamedCurve = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(namedSpec).build();
+ KeyGeneratorTestable kgtOnDefaultCurve = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).keysize(curve.getBits()).build();
// This is some nasty hacking...
KeyGeneratorTestable theKgt = new KeyGeneratorTestable(kpg) {
@@ -156,7 +156,7 @@ public abstract class StandaloneForeignSuite extends StandaloneTestSuite {
for (EC_Key.Public pub : keys) {
ECPublicKey ecpub = ECUtil.toPublicKey(pub);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpub, theKgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(theKgt).random(getRandom()).build();
Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE);
specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " invalid key test.", keyAgreement));
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java
index 657c2ff..87ad0b3 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java
@@ -7,6 +7,7 @@ import cz.crcs.ectester.common.test.CompoundTest;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.Test;
import cz.crcs.ectester.common.util.ByteUtil;
+import cz.crcs.ectester.common.util.ECUtil;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
@@ -80,7 +81,7 @@ public class StandaloneMiscSuite extends StandaloneTestSuite {
private void testCurve(EC_Curve curve, String catName, KeyPairGenerator kpg, Result.ExpectedValue expected) throws NoSuchAlgorithmException {
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, curve.toSpec());
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(curve.toSpec()).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
//perform KeyAgreement tests
@@ -88,7 +89,7 @@ public class StandaloneMiscSuite extends StandaloneTestSuite {
for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) {
if (kaAlgo == null || kaIdent.containsAny(kaTypes)) {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKgt(kgt).privateKgt(kgt).random(getRandom()).build();
kaTests.add(KeyAgreementTest.expectError(testable, expected));
}
}
@@ -101,7 +102,8 @@ public class StandaloneMiscSuite extends StandaloneTestSuite {
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
if (sigAlgo == null || sigIdent.containsAny(sigTypes)) {
Signature sig = sigIdent.getInstance(cfg.selected.getProvider());
- SignatureTestable testable = new SignatureTestable(sig, kgt, hashCurve(curve));
+ byte[] data = sigIdent.toString().getBytes();
+ SignatureTestable testable = new SignatureTestable(sig, kgt, data, getRandom());
sigTests.add(SignatureTest.expectError(testable, expected));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java
index 30a0c0f..46e4141 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java
@@ -38,9 +38,9 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
@Override
protected void runTests() throws Exception {
- String kpgAlgo = cli.getOptionValue("test.kpg-type");
- String kaAlgo = cli.getOptionValue("test.ka-type");
- String sigAlgo = cli.getOptionValue("test.sig-type");
+ String kpgAlgo = cli.getOptionValue("test.kpg-type", "EC");
+ String kaAlgo = cli.getOptionValue("test.ka-type", "ECDH");
+ String sigAlgo = cli.getOptionValue("test.sig-type", "ECDSA");
String keyAlgo = cli.getOptionValue("test.key-type", "AES");
List<String> kpgTypes = kpgAlgo != null ? Arrays.asList(kpgAlgo.split(",")) : new ArrayList<>();
@@ -67,8 +67,8 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider());
if (cli.hasOption("test.bits")) {
int bits = Integer.parseInt(cli.getOptionValue("test.bits"));
- kgtOne = new KeyGeneratorTestable(kpg, bits);
- kgtOther = new KeyGeneratorTestable(kpg, bits);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(bits).random(getRandom()).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(bits).random(getRandom()).build();
} else if (cli.hasOption("test.named-curve")) {
String curveName = cli.getOptionValue("test.named-curve");
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
@@ -77,11 +77,11 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
return;
}
spec = curve.toSpec();
- kgtOne = new KeyGeneratorTestable(kpg, spec);
- kgtOther = new KeyGeneratorTestable(kpg, spec);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
} else {
- kgtOne = new KeyGeneratorTestable(kpg);
- kgtOther = new KeyGeneratorTestable(kpg);
+ kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build();
+ kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build();
}
kpgTests.add(PerformanceTest.repeat(kgtOne, cfg.selected, kpgIdent.getName(), count));
kpgTests.add(PerformanceTest.repeat(kgtOther, cfg.selected, kpgIdent.getName(), count));
@@ -94,9 +94,9 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
KeyAgreementTestable testable;
if (kaIdent.requiresKeyAlgo()) {
- testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec, keyAlgo);
+ testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).keyAlgo(keyAlgo).build();
} else {
- testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec);
+ testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).build();
}
kaTests.add(PerformanceTest.repeat(testable, cfg.selected, kaIdent.getName(), count));
}
@@ -111,10 +111,12 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite {
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
if (sigAlgo == null || sigIdent.containsAny(sigTypes)) {
Signature sig = sigIdent.getInstance(cfg.selected.getProvider());
- sigTests.add(PerformanceTest.repeat(new SignatureTestable(sig, kgtOne, null), cfg.selected, sigIdent.getName(), count));
+ byte[] data = sigIdent.toString().getBytes();
+ sigTests.add(PerformanceTest.repeat(new SignatureTestable(sig, kgtOne, data, getRandom()), cfg.selected, sigIdent.getName(), count));
+ // TODO: The following will always fail as a runTest is not done at this point.
if (kgtOne.getKeyPair() != null) {
ECPrivateKey signKey = (ECPrivateKey) kgtOne.getKeyPair().getPrivate();
- sigTestsNoVerification.add(PerformanceTest.repeat(new SignatureTestable(sig, signKey, null, null), cfg.selected, sigIdent.getName(), count));
+ sigTestsNoVerification.add(PerformanceTest.repeat(new SignatureTestable(sig, signKey, null, data, getRandom()), cfg.selected, sigIdent.getName(), count));
}
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java
index 43feb23..740dca7 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java
@@ -61,11 +61,11 @@ public class StandaloneSignatureSuite extends StandaloneTestSuite {
byte[] data = sig.getSigData();
if (data == null) {
- data = defaultData;
+ data = sigIdent.toString().getBytes();
}
Signature signature = sigIdent.getInstance(cfg.selected.getProvider());
- SignatureTestable testable = new SignatureTestable(signature, ecpub, data, sig.getData(0));
+ SignatureTestable testable = new SignatureTestable(signature, ecpub, data, sig.getData(0), getRandom());
doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "ECDSA test of " + sig.getId() + ".", SignatureTest.expectError(testable, expected)));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
index ac164e1..bfea628 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
@@ -3,6 +3,8 @@ package cz.crcs.ectester.standalone.test.suites;
import cz.crcs.ectester.common.cli.TreeCommandLine;
import cz.crcs.ectester.common.output.TestWriter;
import cz.crcs.ectester.common.test.TestSuite;
+import cz.crcs.ectester.common.util.ByteUtil;
+import cz.crcs.ectester.common.util.Util;
import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.consts.Ident;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
@@ -10,6 +12,7 @@ import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent;
import cz.crcs.ectester.standalone.consts.SignatureIdent;
import cz.crcs.ectester.standalone.libs.ProviderECLibrary;
+import java.security.SecureRandom;
import java.util.Optional;
import java.util.Set;
@@ -19,17 +22,34 @@ import java.util.Set;
public abstract class StandaloneTestSuite extends TestSuite {
TreeCommandLine cli;
ECTesterStandalone.Config cfg;
+ SecureRandom random;
+ byte[] seed;
public StandaloneTestSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli, String name, String... description) {
super(writer, name, description);
this.cfg = cfg;
this.cli = cli;
+ if (cli != null && cli.hasOption("test.prng-seed")) {
+ String seedString = cli.getOptionValue("test.prng-seed");
+ this.seed = ByteUtil.hexToBytes(seedString, true);
+ } else {
+ seed = new SecureRandom().generateSeed(16);
+ }
+ this.random = Util.getRandom(seed);
}
public ProviderECLibrary getLibrary() {
return cfg.selected;
}
+ public byte[] getSeed() {
+ return seed;
+ }
+
+ SecureRandom getRandom() {
+ return this.random;
+ }
+
private <T extends Ident> T getIdent(Set<T> options, String choice, String identName, String defaultChoice) {
T ident;
if (choice == null) {
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java
index 111d354..1766953 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java
@@ -56,7 +56,7 @@ public class StandaloneTestVectorSuite extends StandaloneTestSuite {
KeyAgreementIdent kaIdent = KeyAgreementIdent.get("ECDH");
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, privkey, pubkey);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(privkey).publicKey(pubkey).random(getRandom()).build();
doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test vector " + result.getId(), KeyAgreementTest.match(testable, result.getData(0))));
}
}
diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java
index 4634ab0..1a18188 100644
--- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java
+++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java
@@ -73,11 +73,11 @@ public class StandaloneWrongSuite extends StandaloneTestSuite {
String type = curve.getField() == javacard.security.KeyPair.ALG_EC_FP ? "FP" : "F2M";
//try generating a keypair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY);
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).random(getRandom()).build();
Test ecdh = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE);
doTest(CompoundTest.function(CompoundTest.EXPECT_ALL_SUCCESS, CompoundTest.RUN_ALL_IF_FIRST, "Wrong curve test of " + curve.getBits()
+ "b " + type + ". " + curve.getDesc(), generate, ecdh));
@@ -96,7 +96,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite {
Map<String, EC_Curve> curveMap = EC_Store.getInstance().getObjects(EC_Curve.class, "secg");
List<EC_Curve> curves = curveMap.entrySet().stream().filter((e) -> e.getKey().endsWith("r1") &&
e.getValue().getField() == javacard.security.KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList());
- Random r = new Random();
+ Random r = getRandom();
for (EC_Curve curve : curves) {
short bits = curve.getBits();
final byte[] originalp = curve.getParam(EC_Consts.PARAMETER_FP)[0];
@@ -233,12 +233,12 @@ public class StandaloneWrongSuite extends StandaloneTestSuite {
private Test ecdhTest(ECParameterSpec spec, String desc) throws NoSuchAlgorithmException {
//generate KeyPair
- KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec);
+ KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build();
Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.FAILURE);
//perform ECDH
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt);
+ KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).random(getRandom()).build();
Test ecdh = KeyAgreementTest.expect(testable, Result.ExpectedValue.FAILURE);
return CompoundTest.function(CompoundTest.EXPECT_ALL_SUCCESS, CompoundTest.RUN_ALL_IF_FIRST, desc, generate, ecdh);
}
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile
index 6282574..f947c78 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile
@@ -12,9 +12,9 @@ DEBUG ?= 0
PROJECT_ROOT_PATH ?= ../../../../../../../../../..
ifeq ($(DEBUG), 1)
- CFLAGS+=-g -Wall
+ CFLAGS+=-g -O0 -Wall
LFLAGS+=-g
- CXXFLAGS+=-g -Wall
+ CXXFLAGS+=-g -O0 -Wall
else
CFLAGS+=-O2
LFLAGS+=-O2
@@ -73,6 +73,18 @@ c_utils.o: c_utils.c
lib_timing.so: c_timing.c
$(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_timing.so $<
+prng.o: prng/prng.c
+ $(CC) $(CFLAGS) -c $<
+
+lib_prng.so: c_prng.c
+ $(CC) -o $@ -shared -Wl,-soname,lib_prng.so $(CFLAGS) $<
+
+c_preload.o: c_preload.c
+ $(CC) $(CFLAGS) -c $<
+
+lib_preload.so: c_preload.o prng.o
+ $(CC) -o $@ -shared $(CFLAGS) -ldl -Wl,-soname,lib_preload.so $^
+
lib_csignals.so: c_signals.c
$(CC) -o $@ -shared $(CFLAGS) -pthread -lpthread -Wl,-soname,lib_csignals.so $<
@@ -83,10 +95,14 @@ cpp_utils.o: cpp_utils.cpp
$(CXX) $(CXXFLAGS) -c $<
+clibs: lib_timing.so lib_csignals.so lib_preload.so lib_prng.so
+
+cpplibs: lib_timing.so lib_cppsignals.so lib_preload.so lib_prng.so
+
# OpenSSL shim
openssl: openssl_provider.so
-openssl_provider.so: openssl.o c_utils.o | lib_timing.so lib_csignals.so
+openssl_provider.so: openssl.o c_utils.o | clibs
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs openssl) -l:lib_timing.so -l:lib_csignals.so
openssl.o: openssl.c
@@ -99,7 +115,7 @@ boringssl: boringssl_provider.so
lib_boringssl.so:
cp $(PROJECT_ROOT_PATH)/ext/boringssl/build/crypto/libcrypto.so lib_boringssl.so
-boringssl_provider.so: boringssl.o c_utils.o | lib_timing.so lib_csignals.so lib_boringssl.so
+boringssl_provider.so: boringssl.o c_utils.o | clibs lib_boringssl.so
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_boringssl.so -l:lib_timing.so -l:lib_csignals.so
boringssl.o: boringssl.c
@@ -109,7 +125,7 @@ boringssl.o: boringssl.c
# libgcrypt shim
gcrypt: gcrypt_provider.so
-gcrypt_provider.so: gcrypt.o c_utils.o | lib_timing.so lib_csignals.so
+gcrypt_provider.so: gcrypt.o c_utils.o | clibs
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -pthread -lpthread $(shell libgcrypt-config --libs) -l:lib_timing.so -l:lib_csignals.so
gcrypt.o: gcrypt.c
@@ -119,7 +135,7 @@ gcrypt.o: gcrypt.c
# Libtomcrypt shim
tomcrypt: tomcrypt_provider.so
-tomcrypt_provider.so: tomcrypt.o c_utils.o | lib_timing.so lib_csignals.so
+tomcrypt_provider.so: tomcrypt.o c_utils.o | clibs
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt) -l:lib_timing.so -l:lib_csignals.so
tomcrypt.o: tomcrypt.c
@@ -129,7 +145,7 @@ tomcrypt.o: tomcrypt.c
# Botan-2 shim
botan: botan_provider.so
-botan_provider.so: botan.o cpp_utils.o | lib_timing.so lib_cppsignals.so
+botan_provider.so: botan.o cpp_utils.o | cpplibs
$(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs botan-2) -l:lib_timing.so -l:lib_cppsignals.so
botan.o: botan.cpp
@@ -143,7 +159,7 @@ ifeq ($(shell pkg-config --exists $(CRYPTOPP_NAME); echo $$?),1)
endif
cryptopp: cryptopp_provider.so
-cryptopp_provider.so: cryptopp.o cpp_utils.o | lib_timing.so lib_cppsignals.so
+cryptopp_provider.so: cryptopp.o cpp_utils.o | cpplibs
$(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs $(CRYPTOPP_NAME)) -l:lib_timing.so -l:lib_cppsignals.so
cryptopp.o: cryptopp.cpp
@@ -156,7 +172,7 @@ mbedtls: mbedtls_provider.so
lib_mbedtls.so:
cp $(PROJECT_ROOT_PATH)/ext/mbedtls/build/library/libmbedcrypto.so lib_mbedtls.so
-mbedtls_provider.so: mbedtls.o c_utils.o | lib_timing.so lib_csignals.so lib_mbedtls.so
+mbedtls_provider.so: mbedtls.o c_utils.o | clibs lib_mbedtls.so
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_mbedtls.so -l:lib_timing.so -l:lib_csignals.so
mbedtls.o: mbedtls.c
@@ -169,7 +185,7 @@ ippcp: ippcp_provider.so
lib_ippcp.so:
cp $(PROJECT_ROOT_PATH)/ext/ipp-crypto/build/.build/RELEASE/lib/libippcp.so lib_ippcp.so
-ippcp_provider.so: ippcp.o c_utils.o | lib_timing.so lib_csignals.so lib_ippcp.so
+ippcp_provider.so: ippcp.o c_utils.o | clibs lib_ippcp.so
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_ippcp.so -l:lib_timing.so -l:lib_csignals.so
ippcp.o: ippcp.c
@@ -179,7 +195,7 @@ ippcp.o: ippcp.c
# Nettle shim
nettle: nettle_provider.so
-nettle_provider.so: nettle.o c_utils.o | lib_timing.so lib_csignals.so
+nettle_provider.so: nettle.o c_utils.o | clibs
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs nettle) -l:lib_timing.so -l:lib_csignals.so $(shell pkg-config --libs hogweed) -lgmp
nettle.o: nettle.c
@@ -192,7 +208,7 @@ libressl: libressl_provider.so
lib_libressl.so:
cp $(PROJECT_ROOT_PATH)/ext/libressl/build/crypto/libcrypto.so lib_libressl.so
-libressl_provider.so: libressl.o c_utils.o | lib_timing.so lib_csignals.so lib_libressl.so
+libressl_provider.so: libressl.o c_utils.o | clibs lib_libressl.so
$(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_libressl.so -l:lib_timing.so -l:lib_csignals.so
libressl.o: libressl.c
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp
index 52c8dbb..b3977e1 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp
@@ -4,7 +4,9 @@
#include <botan/version.h>
#include <botan/rng.h>
#include <botan/secmem.h>
+#include <botan/system_rng.h>
#include <botan/auto_rng.h>
+#include <botan/chacha_rng.h>
#include <botan/ec_group.h>
#include <botan/ecc_key.h>
@@ -23,7 +25,7 @@
*/
static jclass provider_class;
-static Botan::AutoSeeded_RNG rng;
+std::unique_ptr<Botan::RandomNumberGenerator> rng = std::make_unique<Botan::AutoSeeded_RNG>();
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider(JNIEnv *env, jobject self) {
/* Create the custom provider. */
@@ -82,7 +84,7 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
init_classes(env, "Botan");
}
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self){
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self) {
jclass set_class = env->FindClass("java/util/TreeSet");
jmethodID set_ctr = env->GetMethodID(set_class, "<init>", "()V");
@@ -99,6 +101,25 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurv
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = env->GetArrayLength(seed);
+ if (seed_length < 32) {
+ fprintf(stderr, "Error setting seed, needs to be at least 32 bytes.\n");
+ return JNI_FALSE;
+ }
+ jbyte *seed_data = env->GetByteArrayElements(seed, nullptr);
+ Botan::secure_vector<uint8_t> vec((uint8_t *)seed_data, (uint8_t *)seed_data + seed_length);
+ Botan::ChaCha_RNG *cha = new Botan::ChaCha_RNG(vec);
+ rng.reset(cha);
+ env->ReleaseByteArrayElements(seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported(JNIEnv *env, jobject self, jint keysize){
return JNI_TRUE;
}
@@ -252,13 +273,13 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
try {
native_timing_start();
if (type_str == "ECDH") {
- skey = std::make_unique<Botan::ECDH_PrivateKey>(rng, group);
+ skey = std::make_unique<Botan::ECDH_PrivateKey>(*rng, group);
} else if (type_str == "ECDSA") {
- skey = std::make_unique<Botan::ECDSA_PrivateKey>(rng, group);
+ skey = std::make_unique<Botan::ECDSA_PrivateKey>(*rng, group);
} else if (type_str == "ECKCDSA") {
- skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(rng, group);
+ skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(*rng, group);
} else if (type_str == "ECGDSA") {
- skey = std::make_unique<Botan::ECGDSA_PrivateKey>(rng, group);
+ skey = std::make_unique<Botan::ECGDSA_PrivateKey>(*rng, group);
}
native_timing_stop();
} catch (Botan::Exception & ex) {
@@ -375,7 +396,7 @@ jbyteArray generate_secret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteAr
Botan::BigInt privkey_scalar((unsigned char *) privkey_data, privkey_length);
env->ReleaseByteArrayElements(privkey, privkey_data, JNI_ABORT);
- Botan::ECDH_PrivateKey skey(rng, curve_group, privkey_scalar);
+ Botan::ECDH_PrivateKey skey(*rng, curve_group, privkey_scalar);
jsize pubkey_length = env->GetArrayLength(pubkey);
jbyte *pubkey_data = env->GetByteArrayElements(pubkey, nullptr);
@@ -402,7 +423,7 @@ jbyteArray generate_secret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteAr
size_t key_len = (get_kdf_bits(env, algorithm) + 7) / 8;
std::string kdf = get_kdf(type_str, &key_len);
- Botan::PK_Key_Agreement ka(skey, rng, kdf);
+ Botan::PK_Key_Agreement ka(skey, *rng, kdf);
std::vector<uint8_t> derived;
try {
@@ -469,11 +490,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
std::unique_ptr<Botan::EC_PrivateKey> skey;
try {
if (type_str.find("ECDSA") != std::string::npos) {
- skey = std::make_unique<Botan::ECDSA_PrivateKey>(rng, curve_group, privkey_scalar);
+ skey = std::make_unique<Botan::ECDSA_PrivateKey>(*rng, curve_group, privkey_scalar);
} else if (type_str.find("ECKCDSA") != std::string::npos) {
- skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(rng, curve_group, privkey_scalar);
+ skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(*rng, curve_group, privkey_scalar);
} else if (type_str.find("ECGDSA") != std::string::npos) {
- skey = std::make_unique<Botan::ECGDSA_PrivateKey>(rng, curve_group, privkey_scalar);
+ skey = std::make_unique<Botan::ECGDSA_PrivateKey>(*rng, curve_group, privkey_scalar);
}
} catch (Botan::Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
@@ -504,10 +525,10 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jbyte *data_bytes = env->GetByteArrayElements(data, nullptr);
std::vector<uint8_t> sig;
try {
- Botan::PK_Signer signer(*skey, rng, emsa, sigformat);
+ Botan::PK_Signer signer(*skey, *rng, emsa, sigformat);
native_timing_start();
- sig = signer.sign_message((uint8_t*) data_bytes, data_length, rng);
+ sig = signer.sign_message((uint8_t*) data_bytes, data_length, *rng);
native_timing_stop();
} catch (Botan::Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c
new file mode 100644
index 0000000..1f597a3
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c
@@ -0,0 +1,316 @@
+#define _GNU_SOURCE
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/random.h>
+#include <sys/syscall.h>
+
+#include "native.h"
+#include "prng/prng.h"
+
+
+#ifdef DEBUG_PRELOAD
+
+void print_buf(uint8_t *buf, size_t len) {
+ for (int i = 0; i < len; ++i) {
+ fprintf(stderr, "%02x ", buf[i]);
+ }
+ fprintf(stderr, "\n");
+}
+
+#else
+
+#define print_buf(buf, len)
+
+#endif
+
+typedef int (*open_t)(const char *pathname, int flags, ...);
+static open_t real_open;
+typedef int (*openat_t)(int fd, const char *pathname, int flags, ...);
+static openat_t real_openat;
+typedef ssize_t (*read_t)(int fd, void *buf, size_t count);
+static read_t real_read;
+typedef FILE *(*fopen_t)(const char *pathname, const char *mode);
+static fopen_t real_fopen;
+typedef size_t (*fread_t)(void *ptr, size_t size, size_t nmemb, FILE *stream);
+static fread_t real_fread;
+typedef ssize_t (*getrandom_t)(void *buf, size_t buflen, unsigned int flags);
+static getrandom_t real_getrandom;
+typedef int (*getentropy_t)(void *buffer, size_t length);
+static getentropy_t real_getentropy;
+typedef long (*syscall_t)(long number, ...);
+static syscall_t real_syscall;
+typedef uint32_t (*arc4random_t)(void);
+static arc4random_t real_arc4random;
+typedef uint32_t (*arc4random_uniform_t)(uint32_t upper_bound);
+static arc4random_uniform_t real_arc4random_uniform;
+typedef void (*arc4random_buf_t)(void *buf, size_t n);
+static arc4random_buf_t real_arc4random_buf;
+
+prng_state preload_prng_state;
+bool preload_prng_enabled = false;
+
+static int *random_fds = NULL;
+static size_t random_fds_used = 0;
+static size_t random_fds_allocd = 0;
+
+void check_random_fds() {
+ if (random_fds_allocd == 0) {
+ random_fds_allocd = 10;
+ random_fds = calloc(random_fds_allocd, sizeof(int));
+ } else if (random_fds_allocd == random_fds_used) {
+ random_fds_allocd *= 2;
+ random_fds = realloc(random_fds, random_fds_allocd * sizeof(int));
+ }
+}
+
+void store_random_fd(int fd) {
+ check_random_fds();
+ random_fds[random_fds_used++] = fd;
+}
+
+int open(const char *pathname, int flags, ...) {
+ if (!real_open) {
+ real_open = dlsym(RTLD_NEXT, "open");
+ }
+
+ va_list args;
+ va_start(args, flags);
+ int mode = va_arg(args, int);
+ va_end(args);
+
+ int result = real_open(pathname, flags, mode);
+ if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) {
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called open(%s, %i, %i)\n", pathname, flags, mode);
+#endif
+ store_random_fd(result);
+ }
+ return result;
+}
+
+int openat(int fd, const char *pathname, int flags, ...) {
+ if (!real_openat) {
+ real_openat = dlsym(RTLD_NEXT, "openat");
+ }
+
+ va_list args;
+ va_start(args, flags);
+ int mode = va_arg(args, int);
+ va_end(args);
+
+ int result = real_openat(fd, pathname, flags, mode);
+ if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) {
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called openat(%s, %i, %i)\n", pathname, flags, mode);
+#endif
+ store_random_fd(result);
+ }
+ return result;
+}
+
+ssize_t read(int fd, void *buf, size_t count) {
+ if (!real_read) {
+ real_read = dlsym(RTLD_NEXT, "read");
+ }
+
+ if (preload_prng_enabled) {
+ for (int i = 0; i < random_fds_used; ++i) {
+ int random_fd = random_fds[i];
+ if (random_fd == fd) {
+ prng_get(&preload_prng_state, buf, count);
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "read from random\n");
+ print_buf(buf, count);
+#endif
+ return count;
+ }
+ }
+ }
+
+ return real_read(fd, buf, count);
+}
+
+static FILE **random_files = NULL;
+static size_t random_files_used = 0;
+static size_t random_files_allocd = 0;
+
+void check_random_files() {
+ if (random_files_allocd == 0) {
+ random_files_allocd = 10;
+ random_files = calloc(random_files_allocd, sizeof(FILE *));
+ } else if (random_files_allocd == random_files_used) {
+ random_files_allocd *= 2;
+ random_files = realloc(random_files, random_files_allocd * sizeof(FILE*));
+ }
+}
+
+void store_random_file(FILE *file) {
+ check_random_files();
+ random_files[random_files_used++] = file;
+}
+
+FILE *fopen(const char *pathname, const char *mode) {
+ if (!real_fopen) {
+ real_fopen = dlsym(RTLD_NEXT, "fopen");
+ }
+
+ FILE *result = real_fopen(pathname, mode);
+
+ if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) {
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called fopen(%s, %s)\n", pathname, mode);
+#endif
+ store_random_file(result);
+ }
+ return result;
+}
+
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
+ if (!real_fread) {
+ real_fread = dlsym(RTLD_NEXT, "fread");
+ }
+
+ if (preload_prng_enabled) {
+ for (int i = 0; i < random_files_used; ++i) {
+ FILE *random_file = random_files[i];
+ if (random_file == stream) {
+ prng_get(&preload_prng_state, ptr, size * nmemb);
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "fread from random\n");
+ print_buf(ptr, size * nmemb);
+#endif
+ return size * nmemb;
+ }
+ }
+ }
+
+ return real_fread(ptr, size, nmemb, stream);
+}
+
+ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) {
+ if (!real_getrandom) {
+ real_getrandom = dlsym(RTLD_NEXT, "getrandom");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called getrandom(*, %lu, %u)\n", buflen, flags);
+#endif
+ if (preload_prng_enabled) {
+ prng_get(&preload_prng_state, buf, buflen);
+ print_buf(buf, buflen);
+ return buflen;
+ } else {
+ return real_getrandom(buf, buflen, flags);
+ }
+}
+
+int getentropy(void *buffer, size_t length) {
+ if (!real_getentropy) {
+ real_getentropy = dlsym(RTLD_NEXT, "getentropy");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called getentropy(*, %lu)\n", length);
+#endif
+ if (preload_prng_enabled) {
+ prng_get(&preload_prng_state, buffer, length);
+ print_buf(buffer, length);
+ return 0;
+ } else {
+ return real_getentropy(buffer, length);
+ }
+}
+
+long syscall(long number, ...) {
+ if (!real_syscall) {
+ real_syscall = dlsym(RTLD_NEXT, "syscall");
+ }
+ va_list args;
+
+ va_start(args, number);
+ long int a0 = va_arg(args, long int);
+ long int a1 = va_arg(args, long int);
+ long int a2 = va_arg(args, long int);
+ long int a3 = va_arg(args, long int);
+ long int a4 = va_arg(args, long int);
+ long int a5 = va_arg(args, long int);
+ va_end(args);
+
+ if (number == SYS_getrandom) {
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called syscall(getrandom, %li, %li, %li, %li, %li, %li)\n", a0, a1, a2, a3, a4, a5);
+#endif
+ if (preload_prng_enabled) {
+ uint8_t *buf = (uint8_t*)a0;
+ long n = a1;
+ prng_get(&preload_prng_state, buf, n);
+ print_buf(buf, n);
+ return n;
+ }
+ }
+ return real_syscall(number, a0, a1, a2, a3, a4, a5);
+}
+
+uint32_t arc4random(void) {
+ if (!real_arc4random) {
+ real_arc4random = dlsym(RTLD_NEXT, "arc4random");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called arc4random\n");
+#endif
+ if (preload_prng_enabled) {
+ uint32_t val = 0;
+ prng_get(&preload_prng_state, (uint8_t*)&val, sizeof(val));
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "%u\n", val);
+#endif
+ return val;
+ } else {
+ return real_arc4random();
+ }
+}
+
+uint32_t arc4random_uniform(uint32_t upper_bound) {
+ if (!real_arc4random_uniform) {
+ real_arc4random_uniform = dlsym(RTLD_NEXT, "arc4random_uniform");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called arc4random_uniform(%u)\n", upper_bound);
+#endif
+ if (preload_prng_enabled) {
+ uint64_t val = 0;
+ prng_get(&preload_prng_state, (uint8_t*)&val, sizeof(val));
+ uint32_t result = (uint32_t)(val % (uint64_t)upper_bound);
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "%u\n", result);
+#endif
+ return result;
+ } else {
+ return real_arc4random_uniform(upper_bound);
+ }
+}
+
+void arc4random_buf(void *buf, size_t n) {
+ if (!real_arc4random_buf) {
+ real_arc4random_buf = dlsym(RTLD_NEXT, "arc4random_buf");
+ }
+
+#ifdef DEBUG_PRELOAD
+ fprintf(stderr, "called arc4random_buf(%p, %lu) = ", buf, n);
+#endif
+ if (preload_prng_enabled) {
+ prng_get(&preload_prng_state, buf, n);
+ print_buf(buf, n);
+ } else {
+ real_arc4random_buf(buf, n);
+ }
+} \ No newline at end of file
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c
new file mode 100644
index 0000000..13bd172
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c
@@ -0,0 +1,18 @@
+#include <jni.h>
+#include <stdbool.h>
+#include "prng/prng.h"
+
+extern prng_state preload_prng_state;
+extern bool preload_prng_enabled;
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+
+ preload_prng_enabled = true;
+ prng_init(&preload_prng_state);
+ prng_seed(&preload_prng_state, seed_data, seed_length);
+
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+} \ No newline at end of file
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
index c4c74a6..1f82f8a 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
@@ -22,8 +22,12 @@ using CryptoPP::Exception;
using CryptoPP::byte;
#include "cryptopp/osrng.h"
+using CryptoPP::RandomNumberGenerator;
using CryptoPP::AutoSeededRandomPool;
+#include "cryptopp/mersenne.h"
+using CryptoPP::MT19937;
+
#include "cryptopp/sha.h"
using CryptoPP::SHA1;
using CryptoPP::SHA224;
@@ -89,7 +93,7 @@ using CryptoPP::Integer;
*/
static jclass provider_class;
-static AutoSeededRandomPool rng;
+static std::unique_ptr<RandomNumberGenerator> rng = std::make_unique<AutoSeededRandomPool>();
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider(JNIEnv *env, jobject self) {
@@ -187,6 +191,23 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getC
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = env->GetArrayLength(seed);
+ if (seed_length > 4) {
+ fprintf(stderr, "Error setting seed, needs to be at most 4 bytes.\n");
+ return JNI_FALSE;
+ }
+ jbyte *seed_data = env->GetByteArrayElements(seed, nullptr);
+ uint32_t seed_int = seed_data[0] | seed_data[1] << 8 | seed_data[2] << 16 | seed_data[3] << 24;
+ rng.reset(new MT19937(seed_int));
+ env->ReleaseByteArrayElements(seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported(JNIEnv *env, jobject self, jint keysize){
std::vector<OID> ecp_oids = get_curve_oids<ECP>();
for (auto & ecp_oid : ecp_oids) {
@@ -517,7 +538,7 @@ template <class EC> jobject generate_from_group(JNIEnv *env, DL_GroupParameters_
SIG_TRY(TIMEOUT) {
try {
native_timing_start();
- ec_domain.GenerateKeyPair(rng, priv, pub);
+ ec_domain.GenerateKeyPair(*rng, priv, pub);
native_timing_stop();
} catch (Exception & ex) {
SIG_DEINIT();
@@ -661,7 +682,7 @@ jbyteArray sign_message(JNIEnv *env, DL_GroupParameters_EC<EC> group, jbyteArray
size_t len;
SIG_TRY(TIMEOUT) {
native_timing_start();
- len = signer.SignMessage(rng, (byte *)data_bytes, data_length, (byte *)signature.c_str());
+ len = signer.SignMessage(*rng, (byte *)data_bytes, data_length, (byte *)signature.c_str());
native_timing_stop();
} SIG_CATCH_HANDLE(env);
env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
index 795c30a..40376f9 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
@@ -25,6 +25,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_create
jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V");
+ gcry_control(GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
const char *running_with = gcry_check_version(GCRYPT_VERSION);
if (!running_with) {
return NULL;
@@ -40,9 +41,8 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_create
JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Gcrypt_setup(JNIEnv *env, jobject this) {
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
- //gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 1);
- gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+ //gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 1);
INIT_PROVIDER(env, provider_class);
@@ -651,4 +651,4 @@ release_init:
gcry_sexp_release(pub_sexp);
gcry_sexp_release(data_sexp);
return result;
-} \ No newline at end of file
+}
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c
index fbf917e..86f0f7e 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c
@@ -136,6 +136,29 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_getCurv
return result;
}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ if (seed_length % 4 != 0) {
+ fprintf(stderr, "Error setting seed, needs to be a multiple of 4 bytes.\n");
+ return JNI_FALSE;
+ }
+ int bn_size;
+ ippsBigNumGetSize(seed_length / 4, &bn_size);
+ uint8_t bn_buf[bn_size];
+ IppsBigNumState *bn = (IppsBigNumState *)bn_buf;
+ ippsBigNumInit(seed_length / 4, bn);
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ ippsSet_BN(IppsBigNumPOS, seed_length / 4, (Ipp32u *) seed_data, bn);
+ ippsPRNGSetSeed(bn, prng_state);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Ippcp_keysizeSupported(JNIEnv *env,
jobject this,
jint keysize) {
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
index 5fc879b..8f5e0fb 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
@@ -16,7 +16,8 @@
static mbedtls_ctr_drbg_context ctr_drbg;
-static mbedtls_entropy_context entropy;
+static mbedtls_entropy_context urandom_entropy;
+static mbedtls_entropy_context fixed_entropy;
static jclass provider_class;
@@ -62,6 +63,17 @@ static int dev_urandom(void *data, unsigned char *output, size_t len, size_t *ol
return 0;
}
+static unsigned char seed_store[32] = {0};
+
+static int fixed_random(void *data, unsigned char *output, size_t len, size_t *olen) {
+ for (size_t i = 0; i < len; ++i) {
+ output[i] = seed_store[i % 32];
+ }
+ *olen = len;
+ return 0;
+}
+
+
static int ctr_drbg_wrapper(void *ctx, unsigned char *buf, size_t len) {
native_timing_pause();
int result = mbedtls_ctr_drbg_random(ctx, buf, len);
@@ -77,9 +89,9 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
ADD_SIG(env, this, "NONEwithECDSA", "MbedTLSECDSAwithNONE");
mbedtls_ctr_drbg_init(&ctr_drbg);
- mbedtls_entropy_init(&entropy);
- mbedtls_entropy_add_source(&entropy, dev_urandom, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);
- mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
+ mbedtls_entropy_init(&urandom_entropy);
+ mbedtls_entropy_add_source(&urandom_entropy, dev_urandom, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);
+ mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &urandom_entropy, NULL, 0);
init_classes(env, "MbedTLS");
}
@@ -101,6 +113,32 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getCu
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_supportsDeterministicPRNG(JNIEnv *env, jobject this) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_setupDeterministicPRNG(JNIEnv *env, jobject this, jbyteArray seed) {
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ if (seed_length > 32) {
+ fprintf(stderr, "Error setting seed, needs to be at most 32 bytes, is %i.\n", seed_length);
+ return JNI_FALSE;
+ }
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ memcpy(seed_store, seed_data, seed_length);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+
+ memset(&ctr_drbg, 0, sizeof(ctr_drbg));
+ mbedtls_ctr_drbg_init(&ctr_drbg);
+
+ mbedtls_entropy_init(&fixed_entropy);
+ // This is NASTY! We are accessing something the library does not want us to.
+ fixed_entropy.private_source_count = 0;
+ mbedtls_entropy_add_source(&fixed_entropy, fixed_random, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);
+ mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &fixed_entropy, NULL, 0);
+
+ return JNI_TRUE;
+}
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_keysizeSupported(JNIEnv *env, jobject this, jint keysize) {
for (const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_list();
curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h
index 60c59b1..881243f 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -47,6 +47,14 @@ JNIEXPORT jstring JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_
JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_getLastNativeTiming
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_NativeECLibrary
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -74,6 +82,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_crea
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -255,6 +279,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createP
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -436,6 +476,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_crea
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -617,6 +673,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_creat
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -1341,6 +1413,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_creat
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getCurves
(JNIEnv *, jobject);
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: supportsDeterministicPRNG
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_supportsDeterministicPRNG
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: setupDeterministicPRNG
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_setupDeterministicPRNG
+ (JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -1522,6 +1610,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_createP
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_getCurves
(JNIEnv *, jobject);
+/*
+* Class: cz_crcs_ectester_standalone_libs_IppcpLib
+* Method: supportsDeterministicPRNG
+* Signature: ()Z
+*/
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_supportsDeterministicPRNG
+(JNIEnv *, jobject);
+
+/*
+* Class: cz_crcs_ectester_standalone_libs_IppcpLib
+* Method: setupDeterministicPRNG
+* Signature: ([B)Z
+*/
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_setupDeterministicPRNG
+(JNIEnv *, jobject, jbyteArray);
+
#ifdef __cplusplus
}
#endif
@@ -1884,6 +1988,21 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_create
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCurves
(JNIEnv *, jobject);
+/*
+* Class: cz_crcs_ectester_standalone_libs_NettleLib
+* Method: supportsDeterministicPRNG
+* Signature: ()Z
+*/
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_supportsDeterministicPRNG
+(JNIEnv *, jobject);
+
+/*
+* Class: cz_crcs_ectester_standalone_libs_NettleLib
+* Method: setupDeterministicPRNG
+* Signature: ([B)Z
+*/
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_setupDeterministicPRNG
+(JNIEnv *, jobject, jbyteArray);
#ifdef __cplusplus
}
#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c
index e7ec00e..08b09d5 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c
@@ -44,10 +44,16 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
init_classes(env, "Nettle");
yarrow256_init(&yarrow, 0, NULL);
- uint8_t file = open("/dev/random", O_RDONLY);
- yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, &file);
- close(file);
-
+ FILE *urandom = fopen("/dev/urandom", "rb");
+ uint8_t seed[YARROW256_SEED_FILE_SIZE];
+ if (urandom) {
+ size_t read = 0;
+ while (read < sizeof(seed)) {
+ read += fread(((uint8_t *)&seed) + read, 1, sizeof(seed) - read, urandom);
+ }
+ fclose(urandom);
+ }
+ yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, seed);
}
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCurves(JNIEnv *env, jobject self) {
@@ -66,6 +72,24 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCur
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ if (seed_length < YARROW256_SEED_FILE_SIZE) {
+ fprintf(stderr, "Error setting seed, needs to be at least %i bytes.\n", YARROW256_SEED_FILE_SIZE);
+ return JNI_FALSE;
+ }
+
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ yarrow256_init(&yarrow, 0, NULL);
+ yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, seed_data);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
static const struct ecc_curve* create_curve_from_name(JNIEnv *env, const char* curve_name) {
if (!curve_name) {
return NULL;
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c
index 59eb0db..5110c8b 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c
@@ -14,6 +14,7 @@
#include <openssl/err.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
+#include <openssl/rand.h>
@@ -69,6 +70,58 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCu
return result;
}
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+static int stdlib_rand_seed(const void *buf, int num)
+{
+ unsigned int s = 0;
+ for (int i = 0; i < num && i < sizeof(unsigned int); ++i) {
+ s |= ((unsigned char*)buf)[i] << 8*i;
+ }
+ srand(s);
+ return 1;
+}
+
+// Fill the buffer with random bytes. For each byte in the buffer, we generate
+// a random number and clamp it to the range of a byte, 0-255.
+static int stdlib_rand_bytes(unsigned char *buf, int num)
+{
+ for (int index = 0; index < num; ++index)
+ {
+ buf[index] = rand() % 256;
+ }
+ return 1;
+}
+
+static void stdlib_rand_cleanup() {}
+static int stdlib_rand_add(const void *buf, int num, double add_entropy)
+{
+ return 1;
+}
+static int stdlib_rand_status()
+{
+ return 1;
+}
+
+RAND_METHOD stdlib_rand_meth = { stdlib_rand_seed,
+ stdlib_rand_bytes,
+ stdlib_rand_cleanup,
+ stdlib_rand_add,
+ stdlib_rand_bytes,
+ stdlib_rand_status
+};
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ RAND_set_rand_method(&stdlib_rand_meth);
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ RAND_seed(seed_data, seed_length);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_keysizeSupported(JNIEnv *env, jobject self, jint keysize) {
size_t ncurves = EC_get_builtin_curves(NULL, 0);
EC_builtin_curve curves[ncurves];
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h
new file mode 100644
index 0000000..6371611
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h
@@ -0,0 +1,37 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakDuplexCommon_h_
+#define _KeccakDuplexCommon_h_
+
+#include "align.h"
+
+#define KCP_DeclareDuplexStructure(prefix, size, alignment) \
+ ALIGN(alignment) typedef struct prefix##_DuplexInstanceStruct { \
+ unsigned char state[size]; \
+ unsigned int rate; \
+ unsigned int byteInputIndex; \
+ unsigned int byteOutputIndex; \
+ } prefix##_DuplexInstance;
+
+#define KCP_DeclareDuplexFunctions(prefix) \
+ int prefix##_DuplexInitialize(prefix##_DuplexInstance *duplexInstance, unsigned int rate, unsigned int capacity); \
+ int prefix##_Duplexing(prefix##_DuplexInstance *duplexInstance, const unsigned char *sigmaBegin, unsigned int sigmaBeginByteLen, unsigned char *Z, unsigned int ZByteLen, unsigned char delimitedSigmaEnd); \
+ int prefix##_DuplexingFeedPartialInput(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned int inputByteLen); \
+ int prefix##_DuplexingFeedZeroes(prefix##_DuplexInstance *duplexInstance, unsigned int inputByteLen); \
+ int prefix##_DuplexingOverwritePartialInput(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned int inputByteLen); \
+ int prefix##_DuplexingOverwriteWithZeroes(prefix##_DuplexInstance *duplexInstance, unsigned int inputByteLen); \
+ int prefix##_DuplexingGetFurtherOutput(prefix##_DuplexInstance *duplexInstance, unsigned char *out, unsigned int outByteLen); \
+ int prefix##_DuplexingGetFurtherOutputAndAdd(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned char *output, unsigned int outputByteLen);
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc
new file mode 100644
index 0000000..bd58043
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc
@@ -0,0 +1,192 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#define JOIN0(a, b) a ## b
+#define JOIN(a, b) JOIN0(a, b)
+
+#define DuplexInstance JOIN(prefix, _DuplexInstance)
+#define DuplexInitialize JOIN(prefix, _DuplexInitialize)
+#define Duplexing JOIN(prefix, _Duplexing)
+#define DuplexingFeedPartialInput JOIN(prefix, _DuplexingFeedPartialInput)
+#define DuplexingFeedZeroes JOIN(prefix, _DuplexingFeedZeroes)
+#define DuplexingOverwritePartialInput JOIN(prefix, _DuplexingOverwritePartialInput)
+#define DuplexingOverwriteWithZeroes JOIN(prefix, _DuplexingOverwriteWithZeroes)
+#define DuplexingGetFurtherOutput JOIN(prefix, _DuplexingGetFurtherOutput)
+#define DuplexingGetFurtherOutputAndAdd JOIN(prefix, _DuplexingGetFurtherOutputAndAdd)
+
+#define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes)
+#define SnP_stateAlignment JOIN(SnP, _stateAlignment)
+#define SnP_StaticInitialize JOIN(SnP, _StaticInitialize)
+#define SnP_Initialize JOIN(SnP, _Initialize)
+#define SnP_AddByte JOIN(SnP, _AddByte)
+#define SnP_AddBytes JOIN(SnP, _AddBytes)
+#define SnP_OverwriteBytes JOIN(SnP, _OverwriteBytes)
+#define SnP_OverwriteWithZeroes JOIN(SnP, _OverwriteWithZeroes)
+#define SnP_ExtractBytes JOIN(SnP, _ExtractBytes)
+#define SnP_ExtractAndAddBytes JOIN(SnP, _ExtractAndAddBytes)
+
+int DuplexInitialize(DuplexInstance *instance, unsigned int rate, unsigned int capacity)
+{
+ if (rate+capacity != SnP_width)
+ return 1;
+ if ((rate <= 2) || (rate > SnP_width))
+ return 1;
+ SnP_StaticInitialize();
+ instance->rate = rate;
+ SnP_Initialize(instance->state);
+ instance->byteInputIndex = 0;
+ instance->byteOutputIndex = (instance->rate+7)/8;
+ return 0;
+}
+
+int Duplexing(DuplexInstance *instance, const unsigned char *sigmaBegin, unsigned int sigmaBeginByteLen, unsigned char *Z, unsigned int ZByteLen, unsigned char delimitedSigmaEnd)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if (delimitedSigmaEnd == 0)
+ return 1;
+ if ((instance->byteInputIndex+sigmaBeginByteLen)*8 > rho_max)
+ return 1;
+ if (rho_max - sigmaBeginByteLen*8 < 7) {
+ unsigned int maxBitsInDelimitedSigmaEnd = rho_max - sigmaBeginByteLen*8;
+ if (delimitedSigmaEnd >= (1 << (maxBitsInDelimitedSigmaEnd+1)))
+ return 1;
+ }
+ if (ZByteLen > (instance->rate+7)/8)
+ return 1; /* The output length must not be greater than the rate (rounded up to a byte) */
+
+ SnP_AddBytes(instance->state, sigmaBegin, instance->byteInputIndex, sigmaBeginByteLen);
+ #ifdef KeccakReference
+ {
+ unsigned char block[SnP_width/8];
+ memcpy(block, sigmaBegin, sigmaBeginByteLen);
+ block[sigmaBeginByteLen] = delimitedSigmaEnd;
+ memset(block+sigmaBeginByteLen+1, 0, sizeof(block)-sigmaBeginByteLen-1);
+ block[(instance->rate-1)/8] |= 1 << ((instance->rate-1) % 8);
+ displayBytes(1, "Block to be absorbed (after padding)", block, (instance->rate+7)/8);
+ }
+ #endif
+
+ /* Last few bits, whose delimiter coincides with first bit of padding */
+ SnP_AddByte(instance->state, delimitedSigmaEnd, instance->byteInputIndex+sigmaBeginByteLen);
+ /* Second bit of padding */
+ SnP_AddByte(instance->state, (unsigned char)1 << ((instance->rate - 1)%8), (instance->rate - 1)/8);
+ SnP_Permute(instance->state);
+ SnP_ExtractBytes(instance->state, Z, 0, ZByteLen);
+
+ if (ZByteLen*8 > instance->rate) {
+ unsigned char mask = (unsigned char)(1 << (instance->rate % 8)) - 1;
+ Z[ZByteLen-1] &= mask;
+ }
+
+ instance->byteInputIndex = 0;
+ instance->byteOutputIndex = ZByteLen;
+
+ return 0;
+}
+
+int DuplexingFeedPartialInput(DuplexInstance *instance, const unsigned char *input, unsigned int inputByteLen)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if ((instance->byteInputIndex+inputByteLen)*8 > rho_max)
+ return 1;
+
+ SnP_AddBytes(instance->state, input, instance->byteInputIndex, inputByteLen);
+ instance->byteInputIndex += inputByteLen;
+ return 0;
+}
+
+int DuplexingFeedZeroes(DuplexInstance *instance, unsigned int inputByteLen)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if ((instance->byteInputIndex+inputByteLen)*8 > rho_max)
+ return 1;
+
+ instance->byteInputIndex += inputByteLen;
+ return 0;
+}
+
+int DuplexingOverwritePartialInput(DuplexInstance *instance, const unsigned char *input, unsigned int inputByteLen)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if ((instance->byteInputIndex+inputByteLen)*8 > rho_max)
+ return 1;
+
+ SnP_OverwriteBytes(instance->state, input, instance->byteInputIndex, inputByteLen);
+ instance->byteInputIndex += inputByteLen;
+ return 0;
+}
+
+int DuplexingOverwriteWithZeroes(DuplexInstance *instance, unsigned int inputByteLen)
+{
+ const unsigned int rho_max = instance->rate - 2;
+
+ if ((instance->byteInputIndex != 0) || (inputByteLen*8 > rho_max))
+ return 1;
+
+ SnP_OverwriteWithZeroes(instance->state, inputByteLen);
+ instance->byteInputIndex = inputByteLen;
+
+ return 0;
+}
+
+int DuplexingGetFurtherOutput(DuplexInstance *instance, unsigned char *output, unsigned int outputByteLen)
+{
+ if ((outputByteLen+instance->byteOutputIndex) > (instance->rate+7)/8)
+ return 1; /* The output length must not be greater than the rate (rounded up to a byte) */
+
+ SnP_ExtractBytes(instance->state, output, instance->byteOutputIndex, outputByteLen);
+ instance->byteOutputIndex += outputByteLen;
+ if (instance->byteOutputIndex*8 > instance->rate) {
+ unsigned char mask = (1 << (instance->rate % 8)) - 1;
+ output[outputByteLen-1] &= mask;
+ }
+ return 0;
+}
+
+int DuplexingGetFurtherOutputAndAdd(DuplexInstance *instance, const unsigned char *input, unsigned char *output, unsigned int outputByteLen)
+{
+ if ((outputByteLen+instance->byteOutputIndex) > (instance->rate+7)/8)
+ return 1; /* The output length must not be greater than the rate (rounded up to a byte) */
+
+ SnP_ExtractAndAddBytes(instance->state, input, output, instance->byteOutputIndex, outputByteLen);
+ instance->byteOutputIndex += outputByteLen;
+ if (instance->byteOutputIndex*8 > instance->rate) {
+ unsigned char mask = (1 << (instance->rate % 8)) - 1;
+ output[outputByteLen-1] &= mask;
+ }
+ return 0;
+}
+
+#undef DuplexInstance
+#undef DuplexInitialize
+#undef Duplexing
+#undef DuplexingFeedPartialInput
+#undef DuplexingFeedZeroes
+#undef DuplexingOverwritePartialInput
+#undef DuplexingOverwriteWithZeroes
+#undef DuplexingGetFurtherOutput
+#undef DuplexingGetFurtherOutputAndAdd
+#undef SnP_stateSizeInBytes
+#undef SnP_stateAlignment
+#undef SnP_StaticInitialize
+#undef SnP_Initialize
+#undef SnP_AddByte
+#undef SnP_AddBytes
+#undef SnP_OverwriteBytes
+#undef SnP_OverwriteWithZeroes
+#undef SnP_ExtractBytes
+#undef SnP_ExtractAndAddBytes
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c
new file mode 100644
index 0000000..d6f56d2
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c
@@ -0,0 +1,29 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#include "KeccakDuplexWidth200.h"
+
+#ifndef KeccakP200_excluded
+ #include "KeccakP-200-SnP.h"
+
+ #define prefix KeccakWidth200
+ #define SnP KeccakP200
+ #define SnP_width 200
+ #define SnP_Permute KeccakP200_Permute_18rounds
+ #include "KeccakDuplex.inc"
+ #undef prefix
+ #undef SnP
+ #undef SnP_width
+ #undef SnP_Permute
+ #undef SnP_FastLoop_Absorb
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h
new file mode 100644
index 0000000..8bb76f4
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h
@@ -0,0 +1,25 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakDuplexWidth200_h_
+#define _KeccakDuplexWidth200_h_
+
+#include "KeccakDuplex-common.h"
+
+#ifndef KeccakP200_excluded
+ #include "KeccakP-200-SnP.h"
+ KCP_DeclareDuplexStructure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment)
+ KCP_DeclareDuplexFunctions(KeccakWidth200)
+#endif
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h
new file mode 100644
index 0000000..4acf932
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h
@@ -0,0 +1,34 @@
+/*
+Implementation by Ronny Van Keer, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+
+---
+
+Please refer to SnP-documentation.h for more details.
+*/
+
+#ifndef _KeccakP_200_SnP_h_
+#define _KeccakP_200_SnP_h_
+
+#define KeccakP200_implementation "8-bit compact implementation"
+#define KeccakP200_stateSizeInBytes 25
+#define KeccakP200_stateAlignment 1
+
+#define KeccakP200_StaticInitialize()
+void KeccakP200_Initialize(void *state);
+void KeccakP200_AddByte(void *state, unsigned char data, unsigned int offset);
+void KeccakP200_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
+void KeccakP200_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
+void KeccakP200_OverwriteWithZeroes(void *state, unsigned int byteCount);
+void KeccakP200_Permute_Nrounds(void *state, unsigned int nrounds);
+void KeccakP200_Permute_18rounds(void *state);
+void KeccakP200_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length);
+void KeccakP200_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c
new file mode 100644
index 0000000..f07bae9
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c
@@ -0,0 +1,187 @@
+/*
+Implementation by Ronny Van Keer, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+
+---
+
+This file implements Keccak-p[200] in a SnP-compatible way.
+Please refer to SnP-documentation.h for more details.
+
+This implementation comes with KeccakP-200-SnP.h in the same folder.
+Please refer to LowLevel.build for the exact list of other files it must be combined with.
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include "KeccakP-200-SnP.h"
+
+// #define DIVISION_INSTRUCTION /* comment if no division instruction or more compact when not using division */
+#define UNROLL_CHILOOP /* comment if more compact using for loop */
+
+typedef unsigned char UINT8;
+typedef unsigned int tSmallUInt; /*INFO It could be more optimized to use "unsigned char" on an 8-bit CPU */
+typedef UINT8 tKeccakLane;
+
+#define ROL8(a, offset) (UINT8)((((UINT8)a) << (offset&7)) ^ (((UINT8)a) >> (8-(offset&7))))
+
+const UINT8 KeccakP200_RotationConstants[25] =
+{
+ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
+};
+
+const UINT8 KeccakP200_PiLane[25] =
+{
+ 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
+};
+
+#if defined(DIVISION_INSTRUCTION)
+#define MOD5(argValue) ((argValue) % 5)
+#else
+const UINT8 KeccakP200_Mod5[10] =
+{
+ 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
+};
+#define MOD5(argValue) KeccakP200_Mod5[argValue]
+#endif
+
+const UINT8 KeccakF200_RoundConstants[] =
+{
+ 0x01, 0x82, 0x8a, 0x00, 0x8b, 0x01, 0x81, 0x09, 0x8a, 0x88, 0x09, 0x0a, 0x8b, 0x8b, 0x89, 0x03, 0x02, 0x80
+};
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_Initialize(void *argState)
+{
+ memset( argState, 0, 25 * sizeof(tKeccakLane) );
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_AddByte(void *argState, unsigned char byte, unsigned int offset)
+{
+ ((tKeccakLane*)argState)[offset] ^= byte;
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_AddBytes(void *argState, const unsigned char *data, unsigned int offset, unsigned int length)
+{
+ tSmallUInt i;
+ tKeccakLane * state = (tKeccakLane*)argState + offset;
+ for(i=0; i<length; i++)
+ state[i] ^= data[i];
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
+{
+ memcpy((unsigned char*)state+offset, data, length);
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_OverwriteWithZeroes(void *state, unsigned int byteCount)
+{
+ memset(state, 0, byteCount);
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_Permute_Nrounds(void *argState, unsigned int nr)
+{
+ tSmallUInt x, y;
+ tKeccakLane temp;
+ tKeccakLane BC[5];
+ tKeccakLane *state;
+ const tKeccakLane *rc;
+
+ state = (tKeccakLane*)argState;
+ rc = KeccakF200_RoundConstants + 18 - nr;
+ do
+ {
+ /* Theta */
+ for ( x = 0; x < 5; ++x )
+ {
+ BC[x] = state[x] ^ state[5 + x] ^ state[10 + x] ^ state[15 + x] ^ state[20 + x];
+ }
+ for ( x = 0; x < 5; ++x )
+ {
+ temp = BC[MOD5(x+4)] ^ ROL8(BC[MOD5(x+1)], 1);
+ for ( y = 0; y < 25; y += 5 )
+ {
+ state[y + x] ^= temp;
+ }
+ }
+
+ /* Rho Pi */
+ temp = state[1];
+ for ( x = 0; x < 24; ++x )
+ {
+ BC[0] = state[KeccakP200_PiLane[x]];
+ state[KeccakP200_PiLane[x]] = ROL8( temp, KeccakP200_RotationConstants[x] );
+ temp = BC[0];
+ }
+
+ /* Chi */
+ for ( y = 0; y < 25; y += 5 )
+ {
+#if defined(UNROLL_CHILOOP)
+ BC[0] = state[y + 0];
+ BC[1] = state[y + 1];
+ BC[2] = state[y + 2];
+ BC[3] = state[y + 3];
+ BC[4] = state[y + 4];
+#else
+ for ( x = 0; x < 5; ++x )
+ {
+ BC[x] = state[y + x];
+ }
+#endif
+ for ( x = 0; x < 5; ++x )
+ {
+ state[y + x] = BC[x] ^((~BC[MOD5(x+1)]) & BC[MOD5(x+2)]);
+ }
+ }
+
+ /* Iota */
+ temp = *(rc++);
+ state[0] ^= temp;
+ }
+ while( temp != 0x80 );
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_Permute_18rounds(void *argState)
+{
+ KeccakP200_Permute_Nrounds(argState, 18);
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length)
+{
+ if (length) {
+ memcpy(data, (UINT8*)state+offset, length);
+ }
+}
+
+/* ---------------------------------------------------------------- */
+
+void KeccakP200_ExtractAndAddBytes(const void *argState, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length)
+{
+ unsigned int i;
+ tKeccakLane * state = (tKeccakLane*)argState + offset;
+ for(i=0; i<length; i++)
+ output[i] = input[i] ^ state[i];
+}
+
+/* ---------------------------------------------------------------- */
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h
new file mode 100644
index 0000000..eca5d2e
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h
@@ -0,0 +1,28 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakPRGCommon_h_
+#define _KeccakPRGCommon_h_
+
+#include "align.h"
+
+#define KCP_DeclareSpongePRG_Structure(prefix, size, alignment) \
+ ALIGN(alignment) typedef struct prefix##_SpongePRG_InstanceStruct { \
+ prefix##_DuplexInstance duplex; \
+ } prefix##_SpongePRG_Instance;
+
+#define KCP_DeclareSpongePRG_Functions(prefix) \
+ int prefix##_SpongePRG_Initialize(prefix##_SpongePRG_Instance *instance, unsigned int capacity); \
+ int prefix##_SpongePRG_Feed(prefix##_SpongePRG_Instance *instance, const unsigned char *input, unsigned int inputByteLen); \
+ int prefix##_SpongePRG_Fetch(prefix##_SpongePRG_Instance *Instance, unsigned char *out, unsigned int outByteLen); \
+ int prefix##_SpongePRG_Forget(prefix##_SpongePRG_Instance *instance);
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h
new file mode 100644
index 0000000..83a2144
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h
@@ -0,0 +1,20 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakPRG_h_
+#define _KeccakPRG_h_
+
+/* For the documentation, please follow the link: */
+/* #include "KeccakPRG-documentation.h" */
+
+#include "KeccakPRGWidth200.h"
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc
new file mode 100644
index 0000000..aa65db0
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc
@@ -0,0 +1,123 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#define JOIN0(a, b) a ## b
+#define JOIN(a, b) JOIN0(a, b)
+
+#define SpongePRG_Instance JOIN(prefix, _SpongePRG_Instance)
+#define SpongePRG_Initialize JOIN(prefix, _SpongePRG_Initialize)
+#define SpongePRG_Feed JOIN(prefix, _SpongePRG_Feed)
+#define SpongePRG_Fetch JOIN(prefix, _SpongePRG_Fetch)
+#define SpongePRG_Forget JOIN(prefix, _SpongePRG_Forget)
+
+#define DuplexInstance JOIN(prefix, _DuplexInstance)
+#define DuplexInitialize JOIN(prefix, _DuplexInitialize)
+#define Duplexing JOIN(prefix, _Duplexing)
+#define DuplexingFeedPartialInput JOIN(prefix, _DuplexingFeedPartialInput)
+#define DuplexingOverwriteWithZeroes JOIN(prefix, _DuplexingOverwriteWithZeroes)
+#define DuplexingGetFurtherOutput JOIN(prefix, _DuplexingGetFurtherOutput)
+#define DuplexGetInputIndex(duplex) (duplex)->byteInputIndex
+#define DuplexGetOutputIndex(duplex) (duplex)->byteOutputIndex
+#define DuplexSetOutputIndex(duplex, i) (duplex)->byteOutputIndex = (i)
+
+int SpongePRG_Initialize(SpongePRG_Instance *instance, unsigned int capacity)
+{
+ unsigned int rate;
+ unsigned int rhoInBytes;
+
+ if (capacity > (SnP_width-10))
+ return 1;
+
+ rate = SnP_width - capacity;
+ rhoInBytes = (rate-2)/8;
+
+ if ( (rhoInBytes == 0) || (rhoInBytes >= SnP_width/8) )
+ return 1;
+ return DuplexInitialize(&instance->duplex, rate, capacity);
+}
+
+int SpongePRG_Feed(SpongePRG_Instance *instance, const unsigned char *input, unsigned int inputByteLen)
+{
+ unsigned int rhoInBytes = (instance->duplex.rate-2)/8;
+ int error = 0;
+
+ while( !error && ((DuplexGetInputIndex(&instance->duplex) + inputByteLen) >= rhoInBytes)) {
+ unsigned int localSize = rhoInBytes - DuplexGetInputIndex(&instance->duplex);
+ error |= DuplexingFeedPartialInput(&instance->duplex, input, localSize);
+ error |= Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01);
+ input += localSize;
+ inputByteLen -= localSize;
+ }
+ if (!error)
+ error = DuplexingFeedPartialInput(&instance->duplex, input, inputByteLen);
+ DuplexSetOutputIndex(&instance->duplex, rhoInBytes);
+ return error;
+}
+
+int SpongePRG_Fetch(SpongePRG_Instance *instance, unsigned char *output, unsigned int outputByteLen)
+{
+ unsigned int rhoInBytes = (instance->duplex.rate-2)/8;
+ int error = 0;
+
+ if (DuplexGetOutputIndex(&instance->duplex) < rhoInBytes) {
+ unsigned int localSize = rhoInBytes - DuplexGetOutputIndex(&instance->duplex);
+ localSize = (localSize <= outputByteLen) ? localSize : outputByteLen;
+ error = DuplexingGetFurtherOutput(&instance->duplex, output, localSize);
+ output += localSize;
+ outputByteLen -= localSize;
+ }
+
+ while( !error && (outputByteLen > 0) ) {
+ error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01);
+ if (!error) {
+ unsigned int localSize = (rhoInBytes <= outputByteLen) ? rhoInBytes : outputByteLen;
+ error = DuplexingGetFurtherOutput(&instance->duplex, output, localSize);
+ output += localSize;
+ outputByteLen -= localSize;
+ }
+ }
+ return error;
+}
+
+int SpongePRG_Forget(SpongePRG_Instance *instance)
+{
+ unsigned int rhoInBytes = (instance->duplex.rate-2)/8;
+ unsigned int capacity = SnP_width - instance->duplex.rate;
+ int error;
+
+ if ((rhoInBytes*8) < capacity)
+ return 1;
+
+ error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01);
+ if ( !error ) {
+ error = DuplexingOverwriteWithZeroes(&instance->duplex, rhoInBytes);
+ if ( !error )
+ error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01);
+ }
+ DuplexSetOutputIndex(&instance->duplex, rhoInBytes);
+ return error;
+}
+
+#undef SpongePRG_Instance
+#undef SpongePRG_Initialize
+#undef SpongePRG_Feed
+#undef SpongePRG_Fetch
+#undef SpongePRG_Forget
+
+#undef DuplexInstance
+#undef DuplexInitialize
+#undef Duplexing
+#undef DuplexingFeedPartialInput
+#undef DuplexingOverwriteWithZeroes
+#undef DuplexingGetFurtherOutput
+#undef DuplexGetInputIndex
+#undef DuplexGetOutputIndex
+#undef DuplexSetOutputIndex
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c
new file mode 100644
index 0000000..067375e
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c
@@ -0,0 +1,22 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#include "KeccakPRGWidth200.h"
+
+#ifndef KeccakP200_excluded
+ #include "KeccakP-200-SnP.h"
+
+ #define prefix KeccakWidth200
+ #define SnP_width 200
+ #include "KeccakPRG.inc"
+ #undef prefix
+ #undef SnP_width
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h
new file mode 100644
index 0000000..d7cfcc9
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h
@@ -0,0 +1,24 @@
+/*
+Implementation by Gilles Van Assche, hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _KeccakPRGWidth200_h_
+#define _KeccakPRGWidth200_h_
+
+#include "KeccakDuplexWidth200.h"
+#include "KeccakPRG-common.h"
+
+#ifndef KeccakP200_excluded
+ #include "KeccakP-200-SnP.h"
+ KCP_DeclareSpongePRG_Structure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment)
+ KCP_DeclareSpongePRG_Functions(KeccakWidth200)
+#endif
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h
new file mode 100644
index 0000000..90c1b37
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h
@@ -0,0 +1,32 @@
+/*
+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
+hereby denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our website:
+https://keccak.team/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef _align_h_
+#define _align_h_
+
+/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */
+#ifdef ALIGN
+#undef ALIGN
+#endif
+
+#if defined(__GNUC__)
+#define ALIGN(x) __attribute__ ((aligned(x)))
+#elif defined(_MSC_VER)
+#define ALIGN(x) __declspec(align(x))
+#elif defined(__ARMCC_VERSION)
+#define ALIGN(x) __align(x)
+#else
+#define ALIGN(x)
+#endif
+
+#endif
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c
new file mode 100644
index 0000000..c44db6f
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c
@@ -0,0 +1,21 @@
+#include "KeccakPRG.h"
+#include "KeccakP-200-compact.c"
+#include "KeccakDuplexWidth200.c"
+#include "KeccakPRGWidth200.c"
+#include "prng.h"
+#include <stdlib.h>
+
+
+void prng_init(prng_state *state) {
+ memset(state, 0, sizeof(state));
+ KeccakWidth200_SpongePRG_Initialize(state, 70);
+}
+
+void prng_seed(prng_state *state, const uint8_t *seed, size_t size) {
+ KeccakWidth200_SpongePRG_Feed(state, seed, size);
+ KeccakWidth200_SpongePRG_Forget(state);
+}
+
+void prng_get(prng_state *state, uint8_t *out, size_t size) {
+ KeccakWidth200_SpongePRG_Fetch(state, out, size);
+} \ No newline at end of file
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h
new file mode 100644
index 0000000..2cc4f21
--- /dev/null
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h
@@ -0,0 +1,13 @@
+#include "KeccakPRG.h"
+#include <stdint.h>
+
+typedef KeccakWidth200_SpongePRG_Instance prng_state;
+
+void prng_init(prng_state *state);
+
+void prng_seed(prng_state *state, const uint8_t *seed, size_t size);
+
+void prng_get(prng_state *state, uint8_t *out, size_t size);
+
+
+
diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
index ec107b8..12c1936 100644
--- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
+++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
@@ -76,6 +76,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getC
return result;
}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) {
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) {
+ yarrow_start(&ltc_prng);
+ jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL);
+ jsize seed_length = (*env)->GetArrayLength(env, seed);
+ yarrow_add_entropy(seed_data, seed_length, &ltc_prng);
+ yarrow_ready(&ltc_prng);
+ (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported(JNIEnv *env, jobject this, jint keysize){
int key_bytes = (keysize + 7) / 8;
const ltc_ecc_set_type * curve = ltc_ecc_sets;
diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java
index d401e58..1ff9556 100644
--- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java
+++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java
@@ -1,6 +1,5 @@
package cz.crcs.ectester.standalone;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java
new file mode 100644
index 0000000..5c7a21f
--- /dev/null
+++ b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java
@@ -0,0 +1,139 @@
+package cz.crcs.ectester.standalone;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junitpioneer.jupiter.StdIo;
+import org.junitpioneer.jupiter.StdOut;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class DeterministicTests {
+
+ static Stream<String> libs() {
+ return Stream.of("Botan", "BouncyCastle", "Crypto++", "IPPCP", "mbedTLS", "Nettle", "OpenSSL", "SunEC", "tomcrypt");
+ // BoringSSL and libgcrypt cannot be easily tested here, because they initialize their RNG only once per process.
+ // LibreSSL hangs in CI.
+ }
+
+ @SuppressWarnings("JUnitMalformedDeclaration")
+ @ParameterizedTest
+ @MethodSource("libs")
+ @StdIo()
+ public void generate(String libName, StdOut out) {
+ String[] args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName};
+ switch (libName) {
+ case "Botan":
+ args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName};
+ break;
+ case "Crypto++":
+ args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName};
+ break;
+ case "Nettle":
+ args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "secp256r1", libName};
+ break;
+ case "mbedTLS":
+ args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", libName};
+ break;
+ }
+ ECTesterStandalone.main(args);
+ String out1 = out.capturedString();
+ ECTesterStandalone.main(args);
+ String out2 = out.capturedString().substring(out1.length());
+ if (!out1.contains(";"))
+ return;
+ List<String> lines1 = out1.lines().collect(Collectors.toList());
+ List<String> lines2 = out2.lines().collect(Collectors.toList());
+ assertEquals(lines1.size(), lines2.size());
+ for (int i = 0; i < lines1.size(); ++i) {
+ String[] parts1 = lines1.get(i).split(";");
+ String[] parts2 = lines2.get(i).split(";");
+ assertEquals(parts1[2], parts2[2]);
+ assertEquals(parts1[3], parts2[3]);
+ }
+ }
+
+ @SuppressWarnings("JUnitMalformedDeclaration")
+ @ParameterizedTest
+ @MethodSource("libs")
+ @StdIo()
+ public void ecdh(String libName, StdOut out) {
+ String[] args = new String[]{"ecdh", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName};
+ switch (libName) {
+ case "Nettle":
+ args = new String[]{"ecdh", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "secp256r1", libName};
+ break;
+ case "Crypto++":
+ args = new String[]{"ecdh", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName};
+ break;
+ case "mbedTLS":
+ args = new String[]{"ecdh", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", libName};
+ break;
+ }
+ ECTesterStandalone.main(args);
+ String out1 = out.capturedString();
+ ECTesterStandalone.main(args);
+ String out2 = out.capturedString().substring(out1.length());
+ if (!out1.contains(";"))
+ return;
+ List<String> lines1 = out1.lines().collect(Collectors.toList());
+ List<String> lines2 = out2.lines().collect(Collectors.toList());
+ assertEquals(lines1.size(), lines2.size());
+ for (int i = 0; i < lines1.size(); ++i) {
+ String[] parts1 = lines1.get(i).split(";");
+ String[] parts2 = lines2.get(i).split(";");
+ assertEquals(parts1[2], parts2[2]); // pubkey
+ assertEquals(parts1[3], parts2[3]); // privkey
+ assertEquals(parts1[4], parts2[4]); // secret
+ }
+ }
+
+ @SuppressWarnings("JUnitMalformedDeclaration")
+ @ParameterizedTest
+ @MethodSource("libs")
+ @StdIo()
+ public void ecdsa(String libName, StdOut out) {
+ String[] args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", libName};
+ switch (libName) {
+ case "Nettle":
+ args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-cn", "secp256r1", "-t", "NONEwithECDSA", libName};
+ break;
+ case "OpenSSL":
+ case "tomcrypt":
+ args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName};
+ break;
+ case "IPPCP":
+ // TODO: Weird, IPPCP cannot sign less than 4 bytes.
+ args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName};
+ break;
+ case "Crypto++":
+ args = new String[]{"ecdsa", "-ps", "12345678", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDSA", libName};
+ break;
+ case "LibreSSL":
+ case "mbedTLS":
+ args = new String[]{"ecdsa", "-ps", "12345678", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName};
+ break;
+ }
+ ECTesterStandalone.main(args);
+ String out1 = out.capturedString();
+ ECTesterStandalone.main(args);
+ String out2 = out.capturedString().substring(out1.length());
+ if (!out1.contains(";"))
+ return;
+ List<String> lines1 = out1.lines().collect(Collectors.toList());
+ List<String> lines2 = out2.lines().collect(Collectors.toList());
+ assertEquals(lines1.size(), lines2.size());
+ for (int i = 0; i < lines1.size(); ++i) {
+ String[] parts1 = lines1.get(i).split(";");
+ String[] parts2 = lines2.get(i).split(";");
+ assertEquals(parts1[3], parts2[3]); // data
+ assertEquals(parts1[4], parts2[4]); // pubkey
+ assertEquals(parts1[5], parts2[5]); // privkey
+ assertEquals(parts1[6], parts2[6]); // signature
+ assertEquals(parts1[7], parts2[7]); // nonce
+ }
+ }
+}