summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cz/crcs/ectester/applet/ECKeyGenerator.java20
-rw-r--r--src/cz/crcs/ectester/applet/ECKeyTester.java62
-rw-r--r--src/cz/crcs/ectester/applet/ECTesterApplet.java333
-rw-r--r--src/cz/crcs/ectester/applet/EC_Consts.java115
-rw-r--r--src/cz/crcs/ectester/common/cli/CLITools.java7
-rw-r--r--src/cz/crcs/ectester/common/cli/Colors.java97
-rw-r--r--src/cz/crcs/ectester/common/cli/ParserOptions.java13
-rw-r--r--src/cz/crcs/ectester/common/cli/TreeParser.java2
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Category.java12
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Curve.java10
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Data.java52
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_KAResult.java2
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Key.java4
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Keypair.java2
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Params.java13
-rw-r--r--src/cz/crcs/ectester/common/output/BaseTextTestWriter.java103
-rw-r--r--src/cz/crcs/ectester/common/output/BaseXMLTestWriter.java75
-rw-r--r--src/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java67
-rw-r--r--src/cz/crcs/ectester/common/output/TeeTestWriter.java43
-rw-r--r--src/cz/crcs/ectester/common/output/TestWriter.java26
-rw-r--r--src/cz/crcs/ectester/common/test/BaseTestable.java14
-rw-r--r--src/cz/crcs/ectester/common/test/CompoundTest.java151
-rw-r--r--src/cz/crcs/ectester/common/test/Result.java28
-rw-r--r--src/cz/crcs/ectester/common/test/SimpleTest.java21
-rw-r--r--src/cz/crcs/ectester/common/test/Test.java59
-rw-r--r--src/cz/crcs/ectester/common/test/TestException.java7
-rw-r--r--src/cz/crcs/ectester/common/test/TestSuite.java76
-rw-r--r--src/cz/crcs/ectester/common/test/TestSuiteException.java13
-rw-r--r--src/cz/crcs/ectester/common/test/Testable.java7
-rw-r--r--src/cz/crcs/ectester/common/util/ByteUtil.java51
-rw-r--r--src/cz/crcs/ectester/common/util/CardUtil.java378
-rw-r--r--src/cz/crcs/ectester/common/util/ECUtil.java10
-rw-r--r--src/cz/crcs/ectester/common/util/FileUtil.java33
-rw-r--r--src/cz/crcs/ectester/data/EC_Store.java54
-rw-r--r--src/cz/crcs/ectester/data/bn/bn158.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn190.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn222.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn254.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn286.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn318.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn350.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn382.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn414.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn446.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn478.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn510.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn542.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn574.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn606.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/bn638.csv1
-rw-r--r--src/cz/crcs/ectester/data/bn/curves.xml100
-rw-r--r--src/cz/crcs/ectester/data/categories.xml55
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor128p128.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor128p16.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor128p2.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor128p32.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor128p4.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor128p64.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor128p8.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor160p16.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor160p2.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor160p32.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor160p4.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor160p64.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor160p8.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor163t128.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor163t16.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor163t2.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor163t32.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor163t4.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor163t64.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor163t8.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor233t128.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor233t16.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor233t2.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor233t32.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor233t4.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor233t64.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/cofactor233t8.csv1
-rw-r--r--src/cz/crcs/ectester/data/cofactor/curves.xml171
-rw-r--r--src/cz/crcs/ectester/data/cofactor/keys.xml707
-rw-r--r--src/cz/crcs/ectester/data/cofactor/secg_keys.xml216
-rw-r--r--src/cz/crcs/ectester/data/composite/carmichael_128.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/carmichael_192.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/carmichael_224.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/carmichael_256.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/carmichael_384.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/carmichael_512.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/carmichael_521.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite128_pq.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite128_pq1.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite128_pq2.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite128_rg0.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite128_small.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite160_pq.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite160_pq1.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite160_pq2.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite160_rg0.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite160_small.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite192_pq.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite192_pq1.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite192_pq2.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite192_rg0.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite192_small.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite224_pq.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite224_pq1.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite224_pq2.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite224_rg0.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite224_small.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite256_pq.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite256_pq1.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite256_pq2.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite256_rg0.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite256_small.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite384.csv2
-rw-r--r--src/cz/crcs/ectester/data/composite/composite384_small.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/composite521.csv2
-rw-r--r--src/cz/crcs/ectester/data/composite/composite521_small.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/curves.xml489
-rw-r--r--src/cz/crcs/ectester/data/composite/keys.xml188
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/10.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/112.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/12.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/128.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/135.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/14.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/140.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/144.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/146.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/148.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/150.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/152.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/152_cofactor.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/16.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/20.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/25.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/2a.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/2b.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/3.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/32.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/4.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/48.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/5.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/6.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/64.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/7.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/70.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/8.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/80.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/90.csv1
-rw-r--r--src/cz/crcs/ectester/data/composite/varying/160/96.csv1
-rw-r--r--src/cz/crcs/ectester/data/degenerate/brainpool.xml362
-rw-r--r--src/cz/crcs/ectester/data/degenerate/keys.xml16
-rw-r--r--src/cz/crcs/ectester/data/degenerate/secg.xml628
-rw-r--r--src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160t1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192t1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224t1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256t1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp112r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp112r2.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp128r1.xml18
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp128r2.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp160r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp160r2.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp192r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp224r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/invalid/secg/secp256r1.xml19
-rw-r--r--src/cz/crcs/ectester/data/other/curve25519.csv1
-rw-r--r--src/cz/crcs/ectester/data/other/curves.xml33
-rw-r--r--src/cz/crcs/ectester/data/other/m221.csv1
-rw-r--r--src/cz/crcs/ectester/data/other/m383.csv1
-rw-r--r--src/cz/crcs/ectester/data/other/m511.csv1
-rw-r--r--src/cz/crcs/ectester/data/schema.xsd7
-rw-r--r--src/cz/crcs/ectester/data/supersingular/curves.xml32
-rw-r--r--src/cz/crcs/ectester/data/supersingular/ss128.csv1
-rw-r--r--src/cz/crcs/ectester/data/supersingular/ss192.csv1
-rw-r--r--src/cz/crcs/ectester/data/supersingular/ss224.csv1
-rw-r--r--src/cz/crcs/ectester/data/supersingular/ss256.csv1
-rw-r--r--src/cz/crcs/ectester/data/wrong/curves.xml13
-rw-r--r--src/cz/crcs/ectester/data/wycheproof/keys.xml894
-rw-r--r--src/cz/crcs/ectester/data/wycheproof/results.xml589
-rw-r--r--src/cz/crcs/ectester/reader/CardMngr.java11
-rw-r--r--src/cz/crcs/ectester/reader/ECTesterReader.java361
-rw-r--r--src/cz/crcs/ectester/reader/command/Command.java406
-rw-r--r--src/cz/crcs/ectester/reader/output/FileTestWriter.java53
-rw-r--r--src/cz/crcs/ectester/reader/output/TextTestWriter.java13
-rw-r--r--src/cz/crcs/ectester/reader/output/XMLTestWriter.java13
-rw-r--r--src/cz/crcs/ectester/reader/output/YAMLTestWriter.java24
-rw-r--r--src/cz/crcs/ectester/reader/response/Response.java204
-rw-r--r--src/cz/crcs/ectester/reader/test/CardCofactorSuite.java77
-rw-r--r--src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java51
-rw-r--r--src/cz/crcs/ectester/reader/test/CardCompositeSuite.java116
-rw-r--r--src/cz/crcs/ectester/reader/test/CardCompressionSuite.java122
-rw-r--r--src/cz/crcs/ectester/reader/test/CardDefaultSuite.java89
-rw-r--r--src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java59
-rw-r--r--src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java189
-rw-r--r--src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java67
-rw-r--r--src/cz/crcs/ectester/reader/test/CardInvalidSuite.java81
-rw-r--r--src/cz/crcs/ectester/reader/test/CardMiscSuite.java60
-rw-r--r--src/cz/crcs/ectester/reader/test/CardTestSuite.java2
-rw-r--r--src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java20
-rw-r--r--src/cz/crcs/ectester/reader/test/CardTwistSuite.java75
-rw-r--r--src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java62
-rw-r--r--src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java58
-rw-r--r--src/cz/crcs/ectester/reader/test/CardWrongSuite.java227
-rw-r--r--src/cz/crcs/ectester/reader/test/CommandTest.java18
-rw-r--r--src/cz/crcs/ectester/reader/test/CommandTestable.java2
-rw-r--r--src/cz/crcs/ectester/reader/test/PerformanceTest.java29
-rw-r--r--src/cz/crcs/ectester/standalone/ECTesterStandalone.java169
-rw-r--r--src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java54
-rw-r--r--src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java4
-rw-r--r--src/cz/crcs/ectester/standalone/libs/CryptoppLib.java20
-rw-r--r--src/cz/crcs/ectester/standalone/libs/MscngLib.java20
-rw-r--r--src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java3
-rw-r--r--src/cz/crcs/ectester/standalone/libs/OpensslLib.java19
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/Makefile83
-rwxr-xr-xsrc/cz/crcs/ectester/standalone/libs/jni/Makefile.bat163
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java78
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java79
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java151
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java97
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java40
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java179
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/botan.cpp244
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/c_utils.c14
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/c_utils.h20
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp24
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp8
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp732
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/mscng.c1210
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/native.h1201
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/openssl.c567
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c42
-rw-r--r--src/cz/crcs/ectester/standalone/output/TextTestWriter.java31
-rw-r--r--src/cz/crcs/ectester/standalone/output/XMLTestWriter.java63
-rw-r--r--src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java65
-rw-r--r--src/cz/crcs/ectester/standalone/test/KeyAgreementTestable.java124
-rw-r--r--src/cz/crcs/ectester/standalone/test/SignatureTestable.java107
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java (renamed from src/cz/crcs/ectester/standalone/test/KeyAgreementTest.java)18
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java170
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java (renamed from src/cz/crcs/ectester/standalone/test/KeyGeneratorTest.java)15
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java (renamed from src/cz/crcs/ectester/standalone/test/KeyGeneratorTestable.java)44
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/SignatureTest.java (renamed from src/cz/crcs/ectester/standalone/test/SignatureTest.java)15
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/SignatureTestable.java130
-rw-r--r--src/cz/crcs/ectester/standalone/test/base/StandaloneTestable.java25
-rw-r--r--src/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java (renamed from src/cz/crcs/ectester/standalone/test/StandaloneDefaultSuite.java)46
-rw-r--r--src/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java (renamed from src/cz/crcs/ectester/standalone/test/StandaloneTestSuite.java)12
251 files changed, 13155 insertions, 2322 deletions
diff --git a/src/cz/crcs/ectester/applet/ECKeyGenerator.java b/src/cz/crcs/ectester/applet/ECKeyGenerator.java
index b026cfe..9150248 100644
--- a/src/cz/crcs/ectester/applet/ECKeyGenerator.java
+++ b/src/cz/crcs/ectester/applet/ECKeyGenerator.java
@@ -139,38 +139,38 @@ public class ECKeyGenerator {
/**
* @param keypair
- * @param corruptParams
- * @param corruption
+ * @param params
+ * @param transformation
* @param buffer
* @param offset
* @return
*/
- public short corruptCurve(KeyPair keypair, short corruptParams, byte corruption, byte[] buffer, short offset) {
- return corruptCurve(keypair, EC_Consts.KEY_BOTH, corruptParams, corruption, buffer, offset);
+ public short transformCurve(KeyPair keypair, short params, short transformation, byte[] buffer, short offset) {
+ return transformCurve(keypair, EC_Consts.KEY_BOTH, params, transformation, buffer, offset);
}
/**
* @param keypair
* @param key
- * @param corruptParams
- * @param corruption
+ * @param params
+ * @param transformation
* @param buffer
* @param offset
* @return
*/
- public short corruptCurve(KeyPair keypair, byte key, short corruptParams, byte corruption, byte[] buffer, short offset) {
+ public short transformCurve(KeyPair keypair, byte key, short params, short transformation, byte[] buffer, short offset) {
sw = ISO7816.SW_NO_ERROR;
- if (corruptParams == EC_Consts.PARAMETERS_NONE) {
+ if (params == EC_Consts.PARAMETERS_NONE) {
return sw;
}
//go through param bit by bit, and invalidate all selected params
short paramMask = EC_Consts.PARAMETER_FP;
while (paramMask <= EC_Consts.PARAMETER_S) {
- short masked = (short) (paramMask & corruptParams);
+ short masked = (short) (paramMask & params);
if (masked != 0) {
short length = exportParameter(keypair, key, masked, buffer, offset);
- length = EC_Consts.corruptParameter(corruption, buffer, offset, length);
+ length = EC_Consts.transformParameter(transformation, buffer, offset, length);
sw = setParameter(keypair, key, masked, buffer, offset, length);
if (sw != ISO7816.SW_NO_ERROR) break;
}
diff --git a/src/cz/crcs/ectester/applet/ECKeyTester.java b/src/cz/crcs/ectester/applet/ECKeyTester.java
index 36515ef..7c091e3 100644
--- a/src/cz/crcs/ectester/applet/ECKeyTester.java
+++ b/src/cz/crcs/ectester/applet/ECKeyTester.java
@@ -52,10 +52,10 @@ public class ECKeyTester {
* @param pubkeyOffset offset into pubkeyBuffer that can be used for the public key
* @param outputBuffer buffer to be used for the secret output
* @param outputOffset offset into the outputBuffer
- * @param corruption (EC_Consts.CORRUPTION_* | ...)
+ * @param transformation (EC_Consts.TRANSFORMATION_* | ...)
* @return derived secret length
**/
- public short testKA(KeyPair privatePair, KeyPair publicPair, byte[] pubkeyBuffer, short pubkeyOffset, byte[] outputBuffer, short outputOffset, short corruption) {
+ public short testKA(KeyPair privatePair, KeyPair publicPair, byte[] pubkeyBuffer, short pubkeyOffset, byte[] outputBuffer, short outputOffset, short transformation) {
short length = 0;
try {
sw = AppletUtil.kaCheck(ecKeyAgreement);
@@ -64,7 +64,7 @@ public class ECKeyTester {
short pubkeyLength = ((ECPublicKey) publicPair.getPublic()).getW(pubkeyBuffer, pubkeyOffset);
ecKeyAgreement.init(privatePair.getPrivate());
- pubkeyLength = EC_Consts.corruptParameter(corruption, pubkeyBuffer, pubkeyOffset, pubkeyLength);
+ pubkeyLength = EC_Consts.transformParameter(transformation, pubkeyBuffer, pubkeyOffset, pubkeyLength);
length = ecKeyAgreement.generateSecret(pubkeyBuffer, pubkeyOffset, pubkeyLength, outputBuffer, outputOffset);
} catch (CardRuntimeException ce) {
sw = ce.getReason();
@@ -79,17 +79,17 @@ public class ECKeyTester {
* @param pubkeyLength
* @param outpuBuffer
* @param outputOffset
- * @param corruption
+ * @param transformation
* @return
*/
- public short testKA_direct(KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outpuBuffer, short outputOffset, short corruption) {
+ public short testKA_direct(KeyPair privatePair, byte[] pubkey, short pubkeyOffset, short pubkeyLength, byte[] outpuBuffer, short outputOffset, short transformation) {
short length = 0;
try {
sw = AppletUtil.kaCheck(ecKeyAgreement);
sw = AppletUtil.keypairCheck(privatePair);
ecKeyAgreement.init(privatePair.getPrivate());
- pubkeyLength = EC_Consts.corruptParameter(corruption, pubkey, pubkeyOffset, pubkeyLength);
+ pubkeyLength = EC_Consts.transformParameter(transformation, pubkey, pubkeyOffset, pubkeyLength);
length = ecKeyAgreement.generateSecret(pubkey, pubkeyOffset, pubkeyLength, outpuBuffer, outputOffset);
} catch (CardRuntimeException ce) {
sw = ce.getReason();
@@ -130,6 +130,56 @@ public class ECKeyTester {
return length;
}
+ /**
+ *
+ * @param signKey
+ * @param inputBuffer
+ * @param inputOffset
+ * @param inputLength
+ * @param sigBuffer
+ * @param sigOffset
+ * @return
+ */
+ public short testECDSA_sign(ECPrivateKey signKey, byte[] inputBuffer, short inputOffset, short inputLength, byte[] sigBuffer, short sigOffset) {
+ short length = 0;
+ try {
+ sw = AppletUtil.signCheck(ecdsaSignature);
+
+ ecdsaSignature.init(signKey, Signature.MODE_SIGN);
+ length = ecdsaSignature.sign(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset);
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
+ /**
+ *
+ * @param verifyKey
+ * @param inputBuffer
+ * @param inputOffset
+ * @param inputLength
+ * @param sigBuffer
+ * @param sigOffset
+ * @param sigLength
+ * @return
+ */
+ public short testECDSA_verify(ECPublicKey verifyKey, byte[] inputBuffer, short inputOffset, short inputLength, byte[] sigBuffer, short sigOffset, short sigLength) {
+ short length = 0;
+ try {
+ sw = AppletUtil.signCheck(ecdsaSignature);
+
+ ecdsaSignature.init(verifyKey, Signature.MODE_VERIFY);
+ boolean correct = ecdsaSignature.verify(inputBuffer, inputOffset, inputLength, sigBuffer, sigOffset, sigLength);
+ if (!correct) {
+ sw = ECTesterApplet.SW_SIG_VERIFY_FAIL;
+ }
+ } catch (CardRuntimeException ce) {
+ sw = ce.getReason();
+ }
+ return length;
+ }
+
public KeyAgreement getKA() {
return ecKeyAgreement;
}
diff --git a/src/cz/crcs/ectester/applet/ECTesterApplet.java b/src/cz/crcs/ectester/applet/ECTesterApplet.java
index 20e3f05..d0ca8f5 100644
--- a/src/cz/crcs/ectester/applet/ECTesterApplet.java
+++ b/src/cz/crcs/ectester/applet/ECTesterApplet.java
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2016-2017 Petr Svenda <petr@svenda.com>
+ * ECTester, tool for testing Elliptic curve cryptography implementations.
+ * Copyright (c) 2016-2018 Petr Svenda <petr@svenda.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -44,16 +45,17 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
public static final byte INS_ALLOCATE = (byte) 0x5a;
public static final byte INS_CLEAR = (byte) 0x5b;
public static final byte INS_SET = (byte) 0x5c;
- public static final byte INS_CORRUPT = (byte) 0x5d;
+ public static final byte INS_TRANSFORM = (byte) 0x5d;
public static final byte INS_GENERATE = (byte) 0x5e;
public static final byte INS_EXPORT = (byte) 0x5f;
public static final byte INS_ECDH = (byte) 0x70;
public static final byte INS_ECDH_DIRECT = (byte) 0x71;
public static final byte INS_ECDSA = (byte) 0x72;
- public static final byte INS_CLEANUP = (byte) 0x73;
- //public static final byte INS_SUPPORT = (byte) 0x74;
- public static final byte INS_ALLOCATE_KA = (byte) 0x75;
- public static final byte INS_ALLOCATE_SIG = (byte) 0x76;
+ public static final byte INS_ECDSA_SIGN = (byte) 0x73;
+ public static final byte INS_ECDSA_VERIFY = (byte) 0x74;
+ public static final byte INS_CLEANUP = (byte) 0x75;
+ public static final byte INS_ALLOCATE_KA = (byte) 0x76;
+ public static final byte INS_ALLOCATE_SIG = (byte) 0x77;
// PARAMETERS for P1 and P2
@@ -70,26 +72,17 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
public static final short SW_KA_NULL = (short) 0x0ee4;
public static final short SW_SIGNATURE_NULL = (short) 0x0ee5;
public static final short SW_OBJECT_NULL = (short) 0x0ee6;
-
-
- // Class javacard.security.KeyAgreement
- // javacard.security.KeyAgreement Fields:
- public static final byte KeyAgreement_ALG_EC_SVDP_DH = 1;
- public static final byte KeyAgreement_ALG_EC_SVDP_DH_KDF = 1;
- public static final byte KeyAgreement_ALG_EC_SVDP_DHC = 2;
- public static final byte KeyAgreement_ALG_EC_SVDP_DHC_KDF = 2;
- public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN = 3;
- public static final byte KeyAgreement_ALG_EC_SVDP_DHC_PLAIN = 4;
- public static final byte KeyAgreement_ALG_EC_PACE_GM = 5;
- public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY = 6;
-
- // Class javacard.security.Signature
- // javacard.security.Signature Fields:
- public static final byte Signature_ALG_ECDSA_SHA = 17;
- public static final byte Signature_ALG_ECDSA_SHA_256 = 33;
- public static final byte Signature_ALG_ECDSA_SHA_384 = 34;
- public static final byte Signature_ALG_ECDSA_SHA_224 = 37;
- public static final byte Signature_ALG_ECDSA_SHA_512 = 38;
+ public static final short SW_Exception = (short) 0xff01;
+ public static final short SW_ArrayIndexOutOfBoundsException = (short) 0xff02;
+ public static final short SW_ArithmeticException = (short) 0xff03;
+ public static final short SW_ArrayStoreException = (short) 0xff04;
+ public static final short SW_NullPointerException = (short) 0xff05;
+ public static final short SW_NegativeArraySizeException = (short) 0xff06;
+ public static final short SW_CryptoException_prefix = (short) 0xf100;
+ public static final short SW_SystemException_prefix = (short) 0xf200;
+ public static final short SW_PINException_prefix = (short) 0xf300;
+ public static final short SW_TransactionException_prefix = (short) 0xf400;
+ public static final short SW_CardRuntimeException_prefix = (short) 0xf500;
private static final short ARRAY_LENGTH = (short) 0xff;
private static final short APDU_MAX_LENGTH = (short) 1024;
@@ -97,8 +90,6 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
private byte[] ramArray = null;
private byte[] ramArray2 = null;
private byte[] apduArray = null;
- // PERSISTENT ARRAY IN EEPROM
- private byte[] dataArray = null; // unused
private RandomData randomData = null;
@@ -123,9 +114,6 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
ramArray2 = JCSystem.makeTransientByteArray(ARRAY_LENGTH, JCSystem.CLEAR_ON_RESET);
apduArray = JCSystem.makeTransientByteArray(APDU_MAX_LENGTH, JCSystem.CLEAR_ON_RESET);
- dataArray = new byte[ARRAY_LENGTH];
- Util.arrayFillNonAtomic(dataArray, (short) 0, ARRAY_LENGTH, (byte) 0);
-
randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
EC_Consts.randomData = randomData;
@@ -152,53 +140,87 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
}
if (cla == CLA_ECTESTERAPPLET) {
- AppletUtil.readAPDU(apdu, apduArray, APDU_MAX_LENGTH);
+ try {
+
+ AppletUtil.readAPDU(apdu, apduArray, APDU_MAX_LENGTH);
+
+ short length = 0;
+ switch (ins) {
+ case INS_ALLOCATE_KA:
+ length = insAllocateKA(apdu);
+ break;
+ case INS_ALLOCATE_SIG:
+ length = insAllocateSig(apdu);
+ break;
+ case INS_ALLOCATE:
+ length = insAllocate(apdu);
+ break;
+ case INS_CLEAR:
+ length = insClear(apdu);
+ break;
+ case INS_SET:
+ length = insSet(apdu);
+ break;
+ case INS_TRANSFORM:
+ length = insTransform(apdu);
+ break;
+ case INS_GENERATE:
+ length = insGenerate(apdu);
+ break;
+ case INS_EXPORT:
+ length = insExport(apdu);
+ break;
+ case INS_ECDH:
+ length = insECDH(apdu);
+ break;
+ case INS_ECDH_DIRECT:
+ length = insECDH_direct(apdu);
+ break;
+ case INS_ECDSA:
+ length = insECDSA(apdu);
+ break;
+ case INS_ECDSA_SIGN:
+ length = insECDSA_sign(apdu);
+ break;
+ case INS_ECDSA_VERIFY:
+ length = insECDSA_verify(apdu);
+ break;
+ case INS_CLEANUP:
+ length = insCleanup(apdu);
+ break;
+ default:
+ // The INS code is not supported by the dispatcher
+ ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
+ break;
+ }
+ apdu.setOutgoingAndSend((short) 0, length);
- short length = 0;
- switch (ins) {
- case INS_ALLOCATE_KA:
- length = insAllocateKA(apdu);
- break;
- case INS_ALLOCATE_SIG:
- length = insAllocateSig(apdu);
- break;
- case INS_ALLOCATE:
- length = insAllocate(apdu);
- break;
- case INS_CLEAR:
- length = insClear(apdu);
- break;
- case INS_SET:
- length = insSet(apdu);
- break;
- case INS_CORRUPT:
- length = insCorrupt(apdu);
- break;
- case INS_GENERATE:
- length = insGenerate(apdu);
- break;
- case INS_EXPORT:
- length = insExport(apdu);
- break;
- case INS_ECDH:
- length = insECDH(apdu);
- break;
- case INS_ECDH_DIRECT:
- length = insECDH_direct(apdu);
- break;
- case INS_ECDSA:
- length = insECDSA(apdu);
- break;
- case INS_CLEANUP:
- length = insCleanup(apdu);
- break;
- default:
- // The INS code is not supported by the dispatcher
- ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
- break;
+ } catch (ISOException e) {
+ throw e; // Our exception from code, just re-emit
+ } catch (ArrayIndexOutOfBoundsException e) {
+ ISOException.throwIt(SW_ArrayIndexOutOfBoundsException);
+ } catch (ArithmeticException e) {
+ ISOException.throwIt(SW_ArithmeticException);
+ } catch (ArrayStoreException e) {
+ ISOException.throwIt(SW_ArrayStoreException);
+ } catch (NullPointerException e) {
+ ISOException.throwIt(SW_NullPointerException);
+ } catch (NegativeArraySizeException e) {
+ ISOException.throwIt(SW_NegativeArraySizeException);
+ } catch (CryptoException e) {
+ ISOException.throwIt((short) (SW_CryptoException_prefix | e.getReason()));
+ } catch (SystemException e) {
+ ISOException.throwIt((short) (SW_SystemException_prefix | e.getReason()));
+ } catch (PINException e) {
+ ISOException.throwIt((short) (SW_PINException_prefix | e.getReason()));
+ } catch (TransactionException e) {
+ ISOException.throwIt((short) (SW_TransactionException_prefix | e.getReason()));
+ } catch (CardRuntimeException e) {
+ ISOException.throwIt((short) (SW_CardRuntimeException_prefix | e.getReason()));
+ } catch (Exception e) {
+ ISOException.throwIt(SW_Exception);
}
- apdu.setOutgoingAndSend((short) 0, length);
} else ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
@@ -304,29 +326,29 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
}
/**
- * Corrupts curve paramaters of local and remote keyPairs.
- * returns corruptCurve SWs
+ * Transforms curve paramaters of local and remote keyPairs.
+ * returns transformCurve SWs
*
* @param apdu P1 = byte keyPair (KEYPAIR_* | ...)
* P2 = byte key (EC_Consts.KEY_* | ...)
* DATA = short params (EC_Consts.PARAMETER_* | ...)
- * byte corruption (EC_Consts.CORRUPTION_* || ...)
+ * short transformation (EC_Consts.TRANSFORMATION_* || ...)
* @return length of response
*/
- private short insCorrupt(APDU apdu) {
+ private short insTransform(APDU apdu) {
byte keyPair = apduArray[ISO7816.OFFSET_P1];
byte key = apduArray[ISO7816.OFFSET_P2];
short cdata = apdu.getOffsetCdata();
short params = Util.getShort(apduArray, cdata);
- byte corruption = apduArray[(short) (cdata + 2)];
+ short transformation = Util.getShort(apduArray, (short) (cdata + 2));
short len = 0;
if ((keyPair & KEYPAIR_LOCAL) != 0) {
- len += corrupt(localKeypair, key, params, corruption, apdu.getBuffer(), (short) 0);
+ len += transform(localKeypair, key, params, transformation, apdu.getBuffer(), (short) 0);
}
if ((keyPair & KEYPAIR_REMOTE) != 0) {
- len += corrupt(remoteKeypair, key, params, corruption, apdu.getBuffer(), len);
+ len += transform(remoteKeypair, key, params, transformation, apdu.getBuffer(), len);
}
return len;
@@ -389,7 +411,7 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
* @param apdu P1 = byte pubkey (KEYPAIR_*)
* P2 = byte privkey (KEYPAIR_*)
* DATA = byte export (EXPORT_TRUE || EXPORT_FALSE)
- * short corruption (EC_Consts.CORRUPTION_* | ...)
+ * short transformation (EC_Consts.TRANSFORMATION_* | ...)
* byte type (EC_Consts.KA_* | ...)
* @return length of response
*/
@@ -398,10 +420,10 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
byte privkey = apduArray[ISO7816.OFFSET_P2];
short cdata = apdu.getOffsetCdata();
byte export = apduArray[cdata];
- short corruption = Util.getShort(apduArray, (short) (cdata + 1));
+ short transformation = Util.getShort(apduArray, (short) (cdata + 1));
byte type = apduArray[(short) (cdata + 3)];
- return ecdh(pubkey, privkey, export, corruption, type, apdu.getBuffer(), (short) 0);
+ return ecdh(pubkey, privkey, export, transformation, type, apdu.getBuffer(), (short) 0);
}
/**
@@ -409,7 +431,7 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
*
* @param apdu P1 = byte privkey (KEYPAIR_*)
* P2 = byte export (EXPORT_TRUE || EXPORT_FALSE)
- * DATA = short corruption (EC_Consts.CORRUPTION_* | ...)
+ * DATA = short transformation (EC_Consts.TRANSFORMATION_* | ...)
* byte type (EC_Consts.KA_* | ...)
* short length
* byte[] pubkey
@@ -419,11 +441,11 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
byte privkey = apduArray[ISO7816.OFFSET_P1];
byte export = apduArray[ISO7816.OFFSET_P2];
short cdata = apdu.getOffsetCdata();
- short corruption = Util.getShort(apduArray, cdata);
+ short transformation = Util.getShort(apduArray, cdata);
byte type = apduArray[(short) (cdata + 2)];
short length = Util.getShort(apduArray, (short) (cdata + 3));
- return ecdh_direct(privkey, export, corruption, type, (short) (cdata + 5), length, apdu.getBuffer(), (short) 0);
+ return ecdh_direct(privkey, export, transformation, type, (short) (cdata + 5), length, apdu.getBuffer(), (short) 0);
}
/**
@@ -455,6 +477,57 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
}
/**
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_*)
+ * P2 = byte export (EXPORT_TRUE || EXPORT_FALSE)
+ * DATA = byte sigType
+ * short dataLength (00 = random data generated, !00 = data length)
+ * byte[] data
+ * @return length of response
+ */
+ private short insECDSA_sign(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte export = apduArray[ISO7816.OFFSET_P2];
+ short cdata = apdu.getOffsetCdata();
+ byte sigType = apduArray[cdata];
+
+ short len = 0;
+ if ((keyPair & KEYPAIR_LOCAL) != 0) {
+ len += ecdsa_sign(localKeypair, sigType, export, apduArray, (short) (cdata + 1), apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & KEYPAIR_REMOTE) != 0) {
+ len += ecdsa_sign(remoteKeypair, sigType, export, apduArray, (short) (cdata + 1), apdu.getBuffer(), len);
+ }
+ return len;
+ }
+
+ /**
+ *
+ * @param apdu P1 = byte keyPair (KEYPAIR_*)
+ * P2 = byte sigType
+ * DATA = short dataLength (00 = random data generated, !00 = data length)
+ * byte[] data
+ * short sigLength
+ * byte[] signature
+ * @return length of response
+ */
+ private short insECDSA_verify(APDU apdu) {
+ byte keyPair = apduArray[ISO7816.OFFSET_P1];
+ byte sigType = apduArray[ISO7816.OFFSET_P2];
+ short cdata = apdu.getOffsetCdata();
+
+ short len = 0;
+ if ((keyPair & KEYPAIR_LOCAL) != 0) {
+ len += ecdsa_verify(localKeypair, sigType, apduArray, cdata, apdu.getBuffer(), (short) 0);
+ }
+ if ((keyPair & KEYPAIR_REMOTE) != 0) {
+ len += ecdsa_verify(remoteKeypair, sigType, apduArray, cdata, apdu.getBuffer(), len);
+ }
+ return len;
+ }
+
+
+ /**
* Performs card memory cleanup via JCSystem.requestObjectDeletion()
*
* @param apdu no data
@@ -536,16 +609,16 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
}
/**
- * @param keyPair KeyPair to corrupt
- * @param key key to corrupt (EC_Consts.KEY_* | ...)
- * @param params parameters to corrupt (EC_Consts.PARAMETER_* | ...)
- * @param corruption corruption type (EC_Consts.CORRUPTION_*)
+ * @param keyPair KeyPair to transform
+ * @param key key to transform (EC_Consts.KEY_* | ...)
+ * @param params parameters to transform (EC_Consts.PARAMETER_* | ...)
+ * @param transformation transformation type (EC_Consts.TRANSFORMATION_*)
* @param outBuffer buffer to output sw to
* @param outOffset output offset in buffer
* @return length of data written to the buffer
*/
- private short corrupt(KeyPair keyPair, byte key, short params, byte corruption, byte[] outBuffer, short outOffset) {
- short sw = keyGenerator.corruptCurve(keyPair, key, params, corruption, ramArray, (short) 0);
+ private short transform(KeyPair keyPair, byte key, short params, short transformation, byte[] outBuffer, short outOffset) {
+ short sw = keyGenerator.transformCurve(keyPair, key, params, transformation, ramArray, (short) 0);
Util.setShort(outBuffer, outOffset, sw);
return 2;
}
@@ -581,7 +654,6 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
length += keyGenerator.exportParameters(keyPair, EC_Consts.KEY_PUBLIC, params, outBuffer, outOffset);
sw = keyGenerator.getSW();
}
- //TODO unify this, now that param key == the passed on param.
if ((key & EC_Consts.KEY_PRIVATE) != 0 && sw == ISO7816.SW_NO_ERROR) {
//export params from private
length += keyGenerator.exportParameters(keyPair, EC_Consts.KEY_PRIVATE, params, outBuffer, (short) (outOffset + length));
@@ -596,13 +668,13 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
* @param pubkey keyPair to use for public key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
* @param privkey keyPair to use for private key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
* @param export whether to export ECDH secret
- * @param corruption whether to invalidate the pubkey before ECDH
+ * @param transformation whether to transform the pubkey before ECDH
* @param type KeyAgreement type to test
* @param outBuffer buffer to write sw to, and export ECDH secret {@code if(export == EXPORT_TRUE)}
* @param outOffset output offset in buffer
* @return length of data written to the buffer
*/
- private short ecdh(byte pubkey, byte privkey, byte export, short corruption, byte type, byte[] outBuffer, short outOffset) {
+ private short ecdh(byte pubkey, byte privkey, byte export, short transformation, byte type, byte[] outBuffer, short outOffset) {
short length = 0;
KeyPair pub = ((pubkey & KEYPAIR_LOCAL) != 0) ? localKeypair : remoteKeypair;
@@ -610,11 +682,11 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
short secretLength = 0;
if (keyTester.getKaType() == type) {
- secretLength = keyTester.testKA(priv, pub, ramArray, (short) 0, ramArray2, (short) 0, corruption);
+ secretLength = keyTester.testKA(priv, pub, ramArray, (short) 0, ramArray2, (short) 0, transformation);
} else {
short allocateSW = keyTester.allocateKA(type);
if (allocateSW == ISO7816.SW_NO_ERROR) {
- secretLength = keyTester.testKA(priv, pub, ramArray, (short) 0, ramArray2, (short) 0, corruption);
+ secretLength = keyTester.testKA(priv, pub, ramArray, (short) 0, ramArray2, (short) 0, transformation);
}
}
Util.setShort(outBuffer, outOffset, keyTester.getSW());
@@ -630,18 +702,18 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
return length;
}
- private short ecdh_direct(byte privkey, byte export, short corruption, byte type, short keyOffset, short keyLength, byte[] outBuffer, short outOffset) {
+ private short ecdh_direct(byte privkey, byte export, short transformation, byte type, short keyOffset, short keyLength, byte[] outBuffer, short outOffset) {
short length = 0;
KeyPair priv = ((privkey & KEYPAIR_LOCAL) != 0) ? localKeypair : remoteKeypair;
short secretLength = 0;
if (keyTester.getKaType() == type) {
- secretLength = keyTester.testKA_direct(priv, apduArray, keyOffset, keyLength, ramArray2, (short) 0, corruption);
+ secretLength = keyTester.testKA_direct(priv, apduArray, keyOffset, keyLength, ramArray2, (short) 0, transformation);
} else {
short allocateSW = keyTester.allocateKA(type);
if (allocateSW == ISO7816.SW_NO_ERROR) {
- secretLength = keyTester.testKA_direct(priv, apduArray, keyOffset, keyLength, ramArray2, (short) 0, corruption);
+ secretLength = keyTester.testKA_direct(priv, apduArray, keyOffset, keyLength, ramArray2, (short) 0, transformation);
}
}
@@ -702,6 +774,63 @@ public class ECTesterApplet extends Applet implements ExtendedLength {
return length;
}
+ private short ecdsa_sign(KeyPair sign, byte sigType, byte export, byte[] inBuffer, short inOffset, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ short dataLength = Util.getShort(inBuffer, inOffset);
+ if (dataLength == 0) { //no data to sign
+ //generate random
+ dataLength = 64;
+ randomData.generateData(ramArray, (short) 0, dataLength);
+ } else {
+ Util.arrayCopyNonAtomic(inBuffer, (short) (inOffset + 2), ramArray, (short) 0, dataLength);
+ }
+
+ short signatureLength = 0;
+ if (keyTester.getSigType() == sigType) {
+ signatureLength = keyTester.testECDSA_sign((ECPrivateKey) sign.getPrivate(), ramArray, (short) 0, dataLength, ramArray2, (short) 0);
+ } else {
+ short allocateSW = keyTester.allocateSig(sigType);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ signatureLength = keyTester.testECDSA_sign((ECPrivateKey) sign.getPrivate(), ramArray, (short) 0, dataLength, ramArray2, (short) 0);
+ }
+ }
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ if (export == EXPORT_TRUE) {
+ Util.setShort(outBuffer, (short) (outOffset + length), signatureLength);
+ length += 2;
+
+ Util.arrayCopyNonAtomic(ramArray2, (short) 0, outBuffer, (short) (outOffset + length), signatureLength);
+ length += signatureLength;
+ }
+
+ return length;
+ }
+
+ private short ecdsa_verify(KeyPair verify, byte sigType, byte[] inBuffer, short inOffset, byte[] outBuffer, short outOffset) {
+ short length = 0;
+
+ short dataLength = Util.getShort(inBuffer, inOffset);
+ short dataOffset = (short)(inOffset + 2);
+ short sigLength = Util.getShort(inBuffer, (short)(dataOffset + dataLength));
+ short sigOffset = (short)(dataOffset + dataLength + 2);
+
+ if (keyTester.getSigType() == sigType) {
+ keyTester.testECDSA_verify((ECPublicKey) verify.getPublic(), inBuffer, dataOffset, dataLength, inBuffer, sigOffset, sigLength);
+ } else {
+ short allocateSW = keyTester.allocateSig(sigType);
+ if (allocateSW == ISO7816.SW_NO_ERROR) {
+ keyTester.testECDSA_verify((ECPublicKey) verify.getPublic(), inBuffer, dataOffset, dataLength, inBuffer, sigOffset, sigLength);
+ }
+ }
+ Util.setShort(outBuffer, outOffset, keyTester.getSW());
+ length += 2;
+
+ return length;
+ }
+
/**
* @param buffer buffer to write sw to
* @param offset output offset in buffer
diff --git a/src/cz/crcs/ectester/applet/EC_Consts.java b/src/cz/crcs/ectester/applet/EC_Consts.java
index 4581fd6..3f3ddb6 100644
--- a/src/cz/crcs/ectester/applet/EC_Consts.java
+++ b/src/cz/crcs/ectester/applet/EC_Consts.java
@@ -12,6 +12,8 @@ import javacard.security.RandomData;
*/
public class EC_Consts {
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_KDF = 1;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC_KDF = 2;
private static byte[] EC_FP_P = null; //p
private static byte[] EC_A = null; //a
private static byte[] EC_B = null; //b
@@ -981,17 +983,19 @@ public class EC_Consts {
public static final short EC571_F2M_K = 2;
- // getCorruptCurveParameter PARAMETER_CORRUPTION TYPES
- public static final short CORRUPTION_NONE = (short) 0x00;
- public static final short CORRUPTION_FIXED = (short) 0x01;
- public static final short CORRUPTION_FULLRANDOM = (short) 0x02;
- public static final short CORRUPTION_ONEBYTERANDOM = (short) 0x04;
- public static final short CORRUPTION_ZERO = (short) 0x08;
- public static final short CORRUPTION_ONE = (short) 0x10;
- public static final short CORRUPTION_MAX = (short) 0x20;
- public static final short CORRUPTION_INCREMENT = (short) 0x40;
- public static final short CORRUPTION_INFINITY = (short) 0x80;
- public static final short CORRUPTION_COMPRESS = (short) 0x0100;
+ // transformParameter TRANSFORMATION types
+ public static final short TRANSFORMATION_NONE = (short) 0x00;
+ public static final short TRANSFORMATION_FIXED = (short) 0x01;
+ public static final short TRANSFORMATION_FULLRANDOM = (short) 0x02;
+ public static final short TRANSFORMATION_ONEBYTERANDOM = (short) 0x04;
+ public static final short TRANSFORMATION_ZERO = (short) 0x08;
+ public static final short TRANSFORMATION_ONE = (short) 0x10;
+ public static final short TRANSFORMATION_MAX = (short) 0x20;
+ public static final short TRANSFORMATION_INCREMENT = (short) 0x40;
+ public static final short TRANSFORMATION_INFINITY = (short) 0x80;
+ public static final short TRANSFORMATION_COMPRESS = (short) 0x0100;
+ public static final short TRANSFORMATION_COMPRESS_HYBRID = (short) 0x0200;
+ public static final short TRANSFORMATION_04_MASK = (short) 0x0400;
// toX962 FORM types
public static final byte X962_UNCOMPRESSED = (byte) 0x00;
@@ -1026,23 +1030,40 @@ public class EC_Consts {
public static final short[] FP_SIZES = new short[]{112, 128, 160, 192, 224, 256, 384, 521};
public static final short[] F2M_SIZES = new short[]{163, 233, 283, 409, 571};
+ // Class javacard.security.KeyAgreement
+ // javacard.security.KeyAgreement Fields:
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH = 1;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC = 2;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN = 3;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DHC_PLAIN = 4;
+ public static final byte KeyAgreement_ALG_EC_PACE_GM = 5;
+ public static final byte KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY = 6;
+
public static final byte[] KA_TYPES = new byte[]{
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH,
- //ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH_KDF, //duplicate
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DHC,
- //ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DHC_KDF, //duplicate
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH_PLAIN,
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DHC_PLAIN,
- ECTesterApplet.KeyAgreement_ALG_EC_PACE_GM,
- ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY
+ KeyAgreement_ALG_EC_SVDP_DH,
+ //KeyAgreement_ALG_EC_SVDP_DH_KDF, //duplicate
+ KeyAgreement_ALG_EC_SVDP_DHC,
+ //KeyAgreement_ALG_EC_SVDP_DHC_KDF, //duplicate
+ KeyAgreement_ALG_EC_SVDP_DH_PLAIN,
+ KeyAgreement_ALG_EC_SVDP_DHC_PLAIN,
+ KeyAgreement_ALG_EC_PACE_GM,
+ KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY
};
+ // Class javacard.security.Signature
+ // javacard.security.Signature Fields:
+ public static final byte Signature_ALG_ECDSA_SHA = 17;
+ public static final byte Signature_ALG_ECDSA_SHA_224 = 37;
+ public static final byte Signature_ALG_ECDSA_SHA_256 = 33;
+ public static final byte Signature_ALG_ECDSA_SHA_384 = 34;
+ public static final byte Signature_ALG_ECDSA_SHA_512 = 38;
+
public static final byte[] SIG_TYPES = new byte[]{
- ECTesterApplet.Signature_ALG_ECDSA_SHA,
- ECTesterApplet.Signature_ALG_ECDSA_SHA_224,
- ECTesterApplet.Signature_ALG_ECDSA_SHA_256,
- ECTesterApplet.Signature_ALG_ECDSA_SHA_384,
- ECTesterApplet.Signature_ALG_ECDSA_SHA_512
+ Signature_ALG_ECDSA_SHA,
+ Signature_ALG_ECDSA_SHA_224,
+ Signature_ALG_ECDSA_SHA_256,
+ Signature_ALG_ECDSA_SHA_384,
+ Signature_ALG_ECDSA_SHA_512
};
public static byte getCurve(short keyLength, byte keyClass) {
@@ -1307,27 +1328,27 @@ public class EC_Consts {
return length;
}
- public static short corruptParameter(short corruption, byte[] buffer, short offset, short length) {
- if (corruption == CORRUPTION_NONE) {
+ public static short transformParameter(short transformation, byte[] buffer, short offset, short length) {
+ if (transformation == TRANSFORMATION_NONE) {
return length;
}
- short corruptionMask = CORRUPTION_FIXED;
- while (corruptionMask <= CORRUPTION_COMPRESS) {
- short corruptionPart = (short) (corruptionMask & corruption);
- switch (corruptionPart) {
+ short transformationMask = TRANSFORMATION_FIXED;
+ while (transformationMask <= TRANSFORMATION_04_MASK) {
+ short transformationPart = (short) (transformationMask & transformation);
+ switch (transformationPart) {
case (short) 0:
break;
- case CORRUPTION_FIXED:
+ case TRANSFORMATION_FIXED:
if (length >= 1) {
buffer[offset] = (byte) 0xcc;
buffer[(short) (offset + length - 1)] = (byte) 0xcc;
}
break;
- case CORRUPTION_FULLRANDOM:
+ case TRANSFORMATION_FULLRANDOM:
randomData.generateData(buffer, offset, length);
break;
- case CORRUPTION_ONEBYTERANDOM:
+ case TRANSFORMATION_ONEBYTERANDOM:
short first = Util.getShort(buffer, (short) 0); // save first two bytes
randomData.generateData(buffer, (short) 0, (short) 2); // generate position
@@ -1345,17 +1366,17 @@ public class EC_Consts {
randomData.generateData(buffer, rngPos, (short) 1);
} while (original == buffer[rngPos]);
break;
- case CORRUPTION_ZERO:
+ case TRANSFORMATION_ZERO:
Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
break;
- case CORRUPTION_ONE:
+ case TRANSFORMATION_ONE:
Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
buffer[(short) (offset + length)] = (byte) 1;
break;
- case CORRUPTION_MAX:
+ case TRANSFORMATION_MAX:
Util.arrayFillNonAtomic(buffer, offset, length, (byte) 1);
break;
- case CORRUPTION_INCREMENT:
+ case TRANSFORMATION_INCREMENT:
short index = (short) (offset + length - 1);
byte value;
do {
@@ -1363,12 +1384,12 @@ public class EC_Consts {
buffer[index--] = ++value;
} while (value == (byte) 0 && index >= offset);
break;
- case CORRUPTION_INFINITY:
+ case TRANSFORMATION_INFINITY:
Util.arrayFillNonAtomic(buffer, offset, length, (byte) 0);
length = 1;
break;
- case CORRUPTION_COMPRESS:
-
+ case TRANSFORMATION_COMPRESS_HYBRID:
+ case TRANSFORMATION_COMPRESS:
if ((short) (length % 2) != 1) {
// an uncompressed point should have odd length (since 1 byte type, + 2 * coords)
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
@@ -1382,13 +1403,19 @@ public class EC_Consts {
buffer[offset] = 2;
}
- length = (short) (half + 1);
+ if (transformationPart == TRANSFORMATION_COMPRESS) {
+ length = (short) (half + 1);
+ } else {
+ buffer[offset] += 4;
+ }
+ break;
+ case TRANSFORMATION_04_MASK:
+ buffer[offset] = 4;
break;
- //TODO: test hybrid form with not corresponding yBit (in first byte value) and y_value in the second half of the param
default:
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
}
- corruptionMask = (short) (corruptionMask << 1);
+ transformationMask = (short) (transformationMask << 1);
}
return length;
}
@@ -1409,7 +1436,7 @@ public class EC_Consts {
break;
case X962_HYBRID:
outputBuffer[offset] = 4;
- case X962_COMPRESSED:
+ case X962_COMPRESSED: /* fallthrough */
byte yLSB = yBuffer[(short) (yOffset + yLength)];
byte yBit = (byte) (yLSB & 0x01);
diff --git a/src/cz/crcs/ectester/common/cli/CLITools.java b/src/cz/crcs/ectester/common/cli/CLITools.java
index 91f121f..a9d036e 100644
--- a/src/cz/crcs/ectester/common/cli/CLITools.java
+++ b/src/cz/crcs/ectester/common/cli/CLITools.java
@@ -22,7 +22,7 @@ public class CLITools {
public static void help(String prog, String header, Options options, String footer, boolean usage) {
HelpFormatter help = new HelpFormatter();
help.setOptionComparator(null);
- help.printHelp(prog, header, options, footer, usage);
+ help.printHelp(Colors.bold(prog), header, options, footer, usage);
}
private static void help(HelpFormatter help, PrintWriter pw, CommandLineParser cli, Options opts, int depth) {
@@ -37,7 +37,8 @@ public class CLITools {
}
tp.getParsers().forEach((key, value) -> {
pw.println();
- help.printWrapped(pw, HelpFormatter.DEFAULT_WIDTH, String.format("%" + depth + "s" + key + ":", " "));
+ String description = value.getDescription() == null ? "" : " | " + value.getDescription() + " |";
+ help.printWrapped(pw, HelpFormatter.DEFAULT_WIDTH, String.format("%" + depth + "s" + key + ":" + description, " "));
CLITools.help(help, pw, value.getParser(), value.getOptions(), depth + 1);
});
}
@@ -96,7 +97,7 @@ public class CLITools {
StringWriter uw = new StringWriter();
PrintWriter upw = new PrintWriter(uw);
usage(help, upw, baseParser, baseOpts);
- pw.print("usage: " + prog);
+ pw.print("usage: " + Colors.bold(prog));
help.printWrapped(pw, HelpFormatter.DEFAULT_WIDTH, uw.toString());
upw.close();
pw.println();
diff --git a/src/cz/crcs/ectester/common/cli/Colors.java b/src/cz/crcs/ectester/common/cli/Colors.java
new file mode 100644
index 0000000..7601088
--- /dev/null
+++ b/src/cz/crcs/ectester/common/cli/Colors.java
@@ -0,0 +1,97 @@
+package cz.crcs.ectester.common.cli;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author Diogo Nunes
+ * @author Jan Jancar johny@neuromancer.sk
+ * Adapted from https://github.com/dialex/JCDP/
+ */
+public class Colors {
+ public static boolean enabled = false;
+
+ public interface ANSIParam {
+ }
+
+ public enum Foreground implements ANSIParam {
+ BLACK("30"), RED("31"), GREEN("32"), YELLOW("33"), BLUE("34"), MAGENTA("35"), CYAN("36"), WHITE("37"), NONE("");
+ private final String code;
+
+ Foreground(String code) {
+ this.code = code;
+ }
+
+ @Override
+ public String toString() {
+ return code;
+ }
+ }
+
+ public enum Background implements ANSIParam {
+ BLACK("40"), RED("41"), GREEN("42"), YELLOW("43"), BLUE("44"), MAGENTA("45"), CYAN("46"), WHITE("47"), NONE("");
+ private final String code;
+
+ Background(String code) {
+ this.code = code;
+ }
+
+ @Override
+ public String toString() {
+ return code;
+ }
+ }
+
+ public enum Attribute implements ANSIParam {
+ CLEAR("0"), BOLD("1"), LIGHT("1"), DARK("2"), UNDERLINE("4"), REVERSE("7"), HIDDEN("8"), NONE("");
+ private final String code;
+
+ Attribute(String code) {
+ this.code = code;
+ }
+
+ @Override
+ public String toString() {
+ return code;
+ }
+ }
+
+ private static final String PREFIX = "\033[";
+ private static final String SEPARATOR = ";";
+ private static final String POSTFIX = "m";
+
+ public static String colored(String text, ANSIParam... params) {
+ if (!enabled) {
+ return text;
+ }
+ Optional<Foreground> fg = Arrays.stream(params).filter(Foreground.class::isInstance).map(Foreground.class::cast).findFirst();
+ Optional<Background> bg = Arrays.stream(params).filter(Background.class::isInstance).map(Background.class::cast).findFirst();
+ List<Attribute> attr = Arrays.stream(params).filter(Attribute.class::isInstance).distinct().map(Attribute.class::cast).collect(Collectors.toList());
+
+ List<ANSIParam> apply = new LinkedList<>();
+ apply.addAll(attr);
+ fg.ifPresent(apply::add);
+ bg.ifPresent(apply::add);
+ List<String> codes = apply.stream().map(Object::toString).collect(Collectors.toList());
+ return PREFIX + String.join(SEPARATOR, codes) + POSTFIX + text + PREFIX + Attribute.CLEAR + POSTFIX;
+ }
+
+ public static String error(String text) {
+ return colored(text, Foreground.RED, Attribute.BOLD);
+ }
+
+ public static String ok(String text) {
+ return colored(text, Foreground.GREEN, Attribute.BOLD);
+ }
+
+ public static String bold(String text) {
+ return colored(text, Attribute.BOLD);
+ }
+
+ public static String underline(String text) {
+ return colored(text, Attribute.UNDERLINE);
+ }
+} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/common/cli/ParserOptions.java b/src/cz/crcs/ectester/common/cli/ParserOptions.java
index ee2097e..7300cbb 100644
--- a/src/cz/crcs/ectester/common/cli/ParserOptions.java
+++ b/src/cz/crcs/ectester/common/cli/ParserOptions.java
@@ -3,25 +3,22 @@ package cz.crcs.ectester.common.cli;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Options;
-import java.util.Collections;
-import java.util.List;
-
/**
* @author Jan Jancar johny@neuromancer.sk
*/
public class ParserOptions {
private CommandLineParser parser;
private Options options;
- private List<Argument> arguments;
+ private String description;
public ParserOptions(CommandLineParser parser, Options options) {
this.parser = parser;
this.options = options;
}
- public ParserOptions(CommandLineParser parser, Options options, List<Argument> arguments) {
+ public ParserOptions(CommandLineParser parser, Options options, String description) {
this(parser, options);
- this.arguments = arguments;
+ this.description = description;
}
public CommandLineParser getParser() {
@@ -32,7 +29,7 @@ public class ParserOptions {
return options;
}
- public List<Argument> getArguments() {
- return Collections.unmodifiableList(arguments);
+ public String getDescription() {
+ return description;
}
}
diff --git a/src/cz/crcs/ectester/common/cli/TreeParser.java b/src/cz/crcs/ectester/common/cli/TreeParser.java
index f1a1980..23f59b1 100644
--- a/src/cz/crcs/ectester/common/cli/TreeParser.java
+++ b/src/cz/crcs/ectester/common/cli/TreeParser.java
@@ -82,7 +82,7 @@ public class TreeParser implements CommandLineParser {
}
} else {
if (required) {
- throw new MissingOptionException(new ArrayList(parsers.keySet()));
+ throw new MissingOptionException(new ArrayList<>(parsers.keySet()));
}
}
diff --git a/src/cz/crcs/ectester/common/ec/EC_Category.java b/src/cz/crcs/ectester/common/ec/EC_Category.java
index 32a788d..9c65f3b 100644
--- a/src/cz/crcs/ectester/common/ec/EC_Category.java
+++ b/src/cz/crcs/ectester/common/ec/EC_Category.java
@@ -1,5 +1,7 @@
package cz.crcs.ectester.common.ec;
+import cz.crcs.ectester.common.cli.Colors;
+
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
@@ -72,13 +74,13 @@ public class EC_Category {
@Override
public String toString() {
StringBuilder out = new StringBuilder();
- out.append("\t- ").append(name).append((desc == null || desc.equals("")) ? "" : ": " + desc);
+ out.append("\t- ").append(Colors.bold(name)).append((desc == null || desc.equals("")) ? "" : ": " + desc);
out.append(System.lineSeparator());
Map<String, EC_Curve> curves = getObjects(EC_Curve.class);
int size = curves.size();
if (size > 0) {
- out.append("\t\tCurves: ");
+ out.append(Colors.bold("\t\tCurves: "));
for (Map.Entry<String, EC_Curve> curve : curves.entrySet()) {
out.append(curve.getKey());
size--;
@@ -91,7 +93,7 @@ public class EC_Category {
Map<String, EC_Key> keys = getObjects(EC_Key.class);
size = keys.size();
if (size > 0) {
- out.append("\t\tKeys: ");
+ out.append(Colors.bold("\t\tKeys: "));
for (Map.Entry<String, EC_Key> key : keys.entrySet()) {
out.append(key.getKey());
size--;
@@ -104,7 +106,7 @@ public class EC_Category {
Map<String, EC_Keypair> keypairs = getObjects(EC_Keypair.class);
size = keypairs.size();
if (size > 0) {
- out.append("\t\tKeypairs: ");
+ out.append(Colors.bold("\t\tKeypairs: "));
for (Map.Entry<String, EC_Keypair> key : keypairs.entrySet()) {
out.append(key.getKey());
size--;
@@ -117,7 +119,7 @@ public class EC_Category {
Map<String, EC_KAResult> results = getObjects(EC_KAResult.class);
size = results.size();
if (size > 0) {
- out.append("\t\tResults: ");
+ out.append(Colors.bold("\t\tResults: "));
for (Map.Entry<String, EC_KAResult> result : results.entrySet()) {
out.append(result.getKey());
size--;
diff --git a/src/cz/crcs/ectester/common/ec/EC_Curve.java b/src/cz/crcs/ectester/common/ec/EC_Curve.java
index 173fd29..6c0d060 100644
--- a/src/cz/crcs/ectester/common/ec/EC_Curve.java
+++ b/src/cz/crcs/ectester/common/ec/EC_Curve.java
@@ -51,10 +51,10 @@ public class EC_Curve extends EC_Params {
@Override
public String toString() {
- return "<" + getId() + "> " + (field == KeyPair.ALG_EC_FP ? "Prime" : "Binary") + " field Elliptic curve (" + String.valueOf(bits) + "b)" + (desc == null ? "" : ": " + desc);
+ return "<" + getId() + "> " + (field == KeyPair.ALG_EC_FP ? "Prime" : "Binary") + " field Elliptic curve (" + String.valueOf(bits) + "b)" + (desc == null ? "" : ": " + desc) + System.lineSeparator() + super.toString();
}
- public ECParameterSpec toSpec() {
+ public EllipticCurve toCurve() {
ECField field;
if (this.field == KeyPair.ALG_EC_FP) {
field = new ECFieldFp(new BigInteger(1, getData(0)));
@@ -71,7 +71,11 @@ public class EC_Curve extends EC_Params {
BigInteger a = new BigInteger(1, getParam(EC_Consts.PARAMETER_A)[0]);
BigInteger b = new BigInteger(1, getParam(EC_Consts.PARAMETER_B)[0]);
- EllipticCurve curve = new EllipticCurve(field, a, b);
+ return new EllipticCurve(field, a, b);
+ }
+
+ public ECParameterSpec toSpec() {
+ EllipticCurve curve = toCurve();
byte[][] G = getParam(EC_Consts.PARAMETER_G);
BigInteger gx = new BigInteger(1, G[0]);
diff --git a/src/cz/crcs/ectester/common/ec/EC_Data.java b/src/cz/crcs/ectester/common/ec/EC_Data.java
index c048ef7..abe6e93 100644
--- a/src/cz/crcs/ectester/common/ec/EC_Data.java
+++ b/src/cz/crcs/ectester/common/ec/EC_Data.java
@@ -14,7 +14,7 @@ import java.util.regex.Pattern;
*
* @author Jan Jancar johny@neuromancer.sk
*/
-public abstract class EC_Data {
+public abstract class EC_Data implements Comparable<EC_Data> {
String id;
int count;
byte[][] data;
@@ -123,7 +123,7 @@ public abstract class EC_Data {
public boolean readCSV(InputStream in) {
Scanner s = new Scanner(in);
- s.useDelimiter(",|;");
+ s.useDelimiter("[,;]");
List<String> data = new LinkedList<>();
while (s.hasNext()) {
String field = s.next();
@@ -214,4 +214,52 @@ public abstract class EC_Data {
}
return Arrays.deepHashCode(this.data);
}
+
+ @Override
+ public int compareTo(EC_Data o) {
+ if (o == this) return 0;
+ if (this.id != null && o.id != null) {
+
+ int minLength = Math.min(this.id.length(), o.id.length());
+ for (int i = 0; i < minLength; i++) {
+ if (this.id.charAt(i) != o.id.charAt(i)) {
+ String thisEnd = this.id.substring(i);
+ String oEnd = o.id.substring(i);
+ try {
+ int thisIndex = Integer.parseInt(thisEnd);
+ int oIndex = Integer.parseInt(oEnd);
+ return Integer.compare(thisIndex, oIndex);
+ } catch (NumberFormatException ignored) {
+ break;
+ }
+ }
+ }
+ return this.id.compareTo(o.id);
+ } else if (this.id == null && o.id == null) {
+ if (Arrays.equals(this.data, o.data)) {
+ return 0;
+ } else {
+ int minCount = (this.count < o.count) ? this.count : o.count;
+ for (int i = 0; i < minCount; ++i) {
+ byte[] thisData = this.data[i];
+ byte[] oData = o.data[i];
+ int innerMinCount = (thisData.length < oData.length) ? thisData.length : oData.length;
+ for (int j = 0; j < innerMinCount; ++j) {
+ if (thisData[j] < oData[j]) {
+ return -1;
+ } else if (thisData[j] > oData[j]) {
+ return 1;
+ }
+ }
+ }
+ }
+ } else {
+ if (this.id == null) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ return 0;
+ }
}
diff --git a/src/cz/crcs/ectester/common/ec/EC_KAResult.java b/src/cz/crcs/ectester/common/ec/EC_KAResult.java
index 8a5fcb4..4e97950 100644
--- a/src/cz/crcs/ectester/common/ec/EC_KAResult.java
+++ b/src/cz/crcs/ectester/common/ec/EC_KAResult.java
@@ -59,7 +59,7 @@ public class EC_KAResult extends EC_Data {
@Override
public String toString() {
- return "<" + getId() + "> " + ka + " result over " + curve + ", " + oneKey + " + " + otherKey + (desc == null ? "" : ": " + desc);
+ return "<" + getId() + "> " + ka + " result over " + curve + ", " + oneKey + " + " + otherKey + (desc == null ? "" : ": " + desc) + System.lineSeparator() + super.toString();
}
}
diff --git a/src/cz/crcs/ectester/common/ec/EC_Key.java b/src/cz/crcs/ectester/common/ec/EC_Key.java
index a34b0e7..754775d 100644
--- a/src/cz/crcs/ectester/common/ec/EC_Key.java
+++ b/src/cz/crcs/ectester/common/ec/EC_Key.java
@@ -54,7 +54,7 @@ public class EC_Key extends EC_Params {
@Override
public String toString() {
- return "<" + getId() + "> EC Public key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc());
+ return "<" + getId() + "> EC Public key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc()) + System.lineSeparator() + super.toString();
}
}
@@ -77,7 +77,7 @@ public class EC_Key extends EC_Params {
@Override
public String toString() {
- return "<" + getId() + "> EC Private key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc());
+ return "<" + getId() + "> EC Private key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc()) + System.lineSeparator() + super.toString();
}
}
}
diff --git a/src/cz/crcs/ectester/common/ec/EC_Keypair.java b/src/cz/crcs/ectester/common/ec/EC_Keypair.java
index 53632cd..24ddba7 100644
--- a/src/cz/crcs/ectester/common/ec/EC_Keypair.java
+++ b/src/cz/crcs/ectester/common/ec/EC_Keypair.java
@@ -36,6 +36,6 @@ public class EC_Keypair extends EC_Params {
@Override
public String toString() {
- return "<" + getId() + "> EC Keypair, over " + curve + (desc == null ? "" : ": " + desc);
+ return "<" + getId() + "> EC Keypair, over " + curve + (desc == null ? "" : ": " + desc) + System.lineSeparator() + super.toString();
}
}
diff --git a/src/cz/crcs/ectester/common/ec/EC_Params.java b/src/cz/crcs/ectester/common/ec/EC_Params.java
index 1c066e7..b08fdfd 100644
--- a/src/cz/crcs/ectester/common/ec/EC_Params.java
+++ b/src/cz/crcs/ectester/common/ec/EC_Params.java
@@ -9,10 +9,11 @@ import java.util.List;
/**
* A list of EC parameters, can contain a subset of the Fp/F2M, A, B, G, R, K, W, S parameters.
- *
+ * <p>
* The set of parameters is uniquely identified by a short bit string.
* The parameters can be exported to a byte array via <code>flatten()</code> or to a comma delimited
* string via <code>expand()</code>.
+ *
* @author Jan Jancar johny@neuromancer.sk
*/
public class EC_Params extends EC_Data {
@@ -61,15 +62,15 @@ public class EC_Params extends EC_Data {
if (masked == EC_Consts.PARAMETER_F2M) {
result = new byte[4][];
result[0] = data[i].clone();
- result[1] = data[i+1].clone();
- result[2] = data[i+2].clone();
- result[3] = data[i+3].clone();
+ result[1] = data[i + 1].clone();
+ result[2] = data[i + 2].clone();
+ result[3] = data[i + 3].clone();
break;
}
if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) {
result = new byte[2][];
result[0] = data[i].clone();
- result[1] = data[i+1].clone();
+ result[1] = data[i + 1].clone();
break;
}
result = new byte[1][];
@@ -189,6 +190,6 @@ public class EC_Params extends EC_Data {
}
paramMask = (short) (paramMask << 1);
}
- return out.toArray(new String[out.size()]);
+ return out.toArray(new String[0]);
}
}
diff --git a/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java b/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java
index 29eb671..ee55069 100644
--- a/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java
+++ b/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java
@@ -1,16 +1,25 @@
package cz.crcs.ectester.common.output;
+import cz.crcs.ectester.common.cli.Colors;
import cz.crcs.ectester.common.test.*;
import java.io.PrintStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
/**
+ * An absctract basis of a TextTestWriter, which outputs in a human readable format, into console.
+ * Requires the implementation of:
+ * <code>String testableString(Testable t)</code>
+ * <code>String deviceString(TestSuite t)</code>
+ *
* @author Jan Jancar johny@neuromancer.sk
*/
public abstract class BaseTextTestWriter implements TestWriter {
private PrintStream output;
- public static int BASE_WIDTH = 90;
+ public static int BASE_WIDTH = 105;
public BaseTextTestWriter(PrintStream output) {
this.output = output;
@@ -18,43 +27,76 @@ public abstract class BaseTextTestWriter implements TestWriter {
@Override
public void begin(TestSuite suite) {
- output.println("═══ Running test suite: " + suite.getName() + " ═══");
- output.println("═══ " + suite.getDescription());
+ output.println("═══ " + Colors.underline("Running test suite:") + " " + Colors.bold(suite.getName()) + " ═══");
+ for (String d : suite.getDescription()) {
+ output.println("═══ " + d);
+ }
+ DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
+ Date date = new Date();
+ output.println("═══ " + Colors.underline("Date:") + " " + dateFormat.format(date));
output.print(deviceString(suite));
}
+ /**
+ * @param t
+ * @return
+ */
protected abstract String testableString(Testable t);
+ /**
+ * @param suite
+ * @return
+ */
protected abstract String deviceString(TestSuite suite);
- private String testString(Test t, String prefix) {
- if (!t.hasRun()) {
- return null;
- }
+ private String testString(Test t, String prefix, int index) {
boolean compound = t instanceof CompoundTest;
+ Result result = t.getResult();
+
+ String line = "";
+ if (prefix.equals("")) {
+ char charLine[] = new char[BASE_WIDTH + 24];
+ new String(new char[BASE_WIDTH + 24]).replace("\0", "━").getChars(0, charLine.length - 1, charLine, 0);
+ charLine[0] = '■';
+ charLine[4] = '┳';
+ charLine[BASE_WIDTH + 1] = '┳';
+ charLine[BASE_WIDTH + 13] = '┳';
+ charLine[BASE_WIDTH + 23] = '┓';
+ line = new String(charLine) + System.lineSeparator();
+ }
+
StringBuilder out = new StringBuilder();
- out.append(t.ok() ? " OK " : "NOK ");
- out.append(compound ? "┳ " : "━ ");
- int width = BASE_WIDTH - (prefix.length() + out.length());
+ out.append(t.ok() ? Colors.ok(" OK ") : Colors.error("NOK "));
+ out.append(compound ? (prefix.equals("") ? "╋ " : "┳ ") : "━ ");
+ int width = BASE_WIDTH - (prefix.length() + 6);
String widthSpec = "%-" + String.valueOf(width) + "s";
- out.append(String.format(widthSpec, t.getDescription()));
+ String desc = ((prefix.equals("")) ? "(" + index + ") " : "") + t.getDescription();
+ out.append(String.format(widthSpec, desc));
out.append(" ┃ ");
- out.append(String.format("%-9s", t.getResultValue().name()));
+ Colors.Foreground valueColor;
+ if (result.getValue().ok()) {
+ valueColor = Colors.Foreground.GREEN;
+ } else if (result.getValue().equals(Result.Value.ERROR)) {
+ valueColor = Colors.Foreground.RED;
+ } else {
+ valueColor = Colors.Foreground.YELLOW;
+ }
+ out.append(Colors.colored(String.format("%-9s", result.getValue().name()), Colors.Attribute.BOLD, valueColor));
out.append(" ┃ ");
if (compound) {
CompoundTest test = (CompoundTest) t;
- out.append(test.getResultCause());
+ out.append(String.valueOf(result.getCause()));
out.append(System.lineSeparator());
- Test[] tests = test.getTests();
+ Test[] tests = test.getStartedTests();
for (int i = 0; i < tests.length; ++i) {
if (i == tests.length - 1) {
out.append(prefix).append(" ┗ ");
- out.append(testString(tests[i], prefix + " "));
+ out.append(testString(tests[i], prefix + " ", index));
} else {
out.append(prefix).append(" ┣ ");
- out.append(testString(tests[i], prefix + " ┃ "));
+ out.append(testString(tests[i], prefix + " ┃ ", index));
}
if (i != tests.length - 1) {
@@ -62,17 +104,38 @@ public abstract class BaseTextTestWriter implements TestWriter {
}
}
} else {
- SimpleTest test = (SimpleTest) t;
+ SimpleTest<? extends BaseTestable> test = (SimpleTest<? extends BaseTestable>) t;
out.append(testableString(test.getTestable()));
}
- return out.toString();
+ return line + out.toString();
}
@Override
- public void outputTest(Test t) {
+ public void outputTest(Test t, int index) {
if (!t.hasRun())
return;
- output.println(testString(t, ""));
+ output.println(testString(t, "", index));
+ output.flush();
+ }
+
+ private String errorString(Throwable error) {
+ StringBuilder sb = new StringBuilder();
+ for (Throwable t = error; t != null; t = t.getCause()) {
+ sb.append("═══ ").append(t.toString()).append(" ═══");
+ sb.append(System.lineSeparator());
+ }
+ sb.append("═══ ═══").append(System.lineSeparator());
+ for (StackTraceElement s : error.getStackTrace()) {
+ sb.append("═══ ").append(s.toString()).append(" ═══");
+ sb.append(System.lineSeparator());
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public void outputError(Test t, Throwable cause, int index) {
+ output.println(testString(t, "", index));
+ output.print(errorString(cause));
output.flush();
}
diff --git a/src/cz/crcs/ectester/common/output/BaseXMLTestWriter.java b/src/cz/crcs/ectester/common/output/BaseXMLTestWriter.java
index f3e9411..53970dd 100644
--- a/src/cz/crcs/ectester/common/output/BaseXMLTestWriter.java
+++ b/src/cz/crcs/ectester/common/output/BaseXMLTestWriter.java
@@ -15,6 +15,9 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -24,6 +27,7 @@ public abstract class BaseXMLTestWriter implements TestWriter {
private DocumentBuilder db;
protected Document doc;
private Node root;
+ private Node tests;
public BaseXMLTestWriter(OutputStream output) throws ParserConfigurationException {
this.output = output;
@@ -35,28 +39,65 @@ public abstract class BaseXMLTestWriter implements TestWriter {
doc = db.newDocument();
Element rootElem = doc.createElement("testSuite");
rootElem.setAttribute("name", suite.getName());
- rootElem.setAttribute("desc", suite.getDescription());
+ rootElem.setAttribute("desc", suite.getTextDescription());
+ DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
+ Date date = new Date();
+ rootElem.setAttribute("date", dateFormat.format(date));
root = rootElem;
doc.appendChild(root);
root.appendChild(deviceElement(suite));
+ tests = doc.createElement("tests");
+ root.appendChild(tests);
}
protected abstract Element testableElement(Testable t);
protected abstract Element deviceElement(TestSuite suite);
- private Element testElement(Test t) {
+ private String causeString(Object cause) {
+ if (cause == null) {
+ return "null";
+ } else if (cause instanceof Throwable) {
+ StringBuilder sb = new StringBuilder();
+ for (Throwable t = (Throwable) cause; t != null; t = t.getCause()) {
+ sb.append(t.toString());
+ sb.append(System.lineSeparator());
+ }
+ return sb.toString();
+ } else {
+ return cause.toString();
+ }
+ }
+
+ private Element resultElement(Result result) {
+ Element resultElem = doc.createElement("result");
+
+ Element ok = doc.createElement("ok");
+ ok.setTextContent(String.valueOf(result.ok()));
+ Element value = doc.createElement("value");
+ value.setTextContent(result.getValue().name());
+ Element cause = doc.createElement("cause");
+ cause.setTextContent(causeString(result.getCause()));
+
+ resultElem.appendChild(ok);
+ resultElem.appendChild(value);
+ resultElem.appendChild(cause);
+
+ return resultElem;
+ }
+
+ private Element testElement(Test t, int index) {
Element testElem;
if (t instanceof CompoundTest) {
CompoundTest test = (CompoundTest) t;
testElem = doc.createElement("test");
testElem.setAttribute("type", "compound");
- for (Test innerTest : test.getTests()) {
- testElem.appendChild(testElement(innerTest));
+ for (Test innerTest : test.getStartedTests()) {
+ testElem.appendChild(testElement(innerTest, -1));
}
} else {
- SimpleTest test = (SimpleTest) t;
+ SimpleTest<? extends BaseTestable> test = (SimpleTest<? extends BaseTestable>) t;
testElem = testableElement(test.getTestable());
}
@@ -64,26 +105,26 @@ public abstract class BaseXMLTestWriter implements TestWriter {
description.setTextContent(t.getDescription());
testElem.appendChild(description);
- Element result = doc.createElement("result");
- Element ok = doc.createElement("ok");
- ok.setTextContent(String.valueOf(t.ok()));
- Element value = doc.createElement("value");
- value.setTextContent(t.getResultValue().name());
- Element cause = doc.createElement("cause");
- cause.setTextContent(t.getResultCause());
- result.appendChild(ok);
- result.appendChild(value);
- result.appendChild(cause);
+ Element result = resultElement(t.getResult());
testElem.appendChild(result);
+ if (index != -1) {
+ testElem.setAttribute("index", String.valueOf(index));
+ }
+
return testElem;
}
@Override
- public void outputTest(Test t) {
+ public void outputTest(Test t, int index) {
if (!t.hasRun())
return;
- root.appendChild(testElement(t));
+ tests.appendChild(testElement(t, index));
+ }
+
+ @Override
+ public void outputError(Test t, Throwable cause, int index) {
+ tests.appendChild(testElement(t, index));
}
@Override
diff --git a/src/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java b/src/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java
index 0769e83..e054563 100644
--- a/src/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java
+++ b/src/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java
@@ -5,10 +5,9 @@ import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.PrintStream;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -26,12 +25,15 @@ public abstract class BaseYAMLTestWriter implements TestWriter {
@Override
public void begin(TestSuite suite) {
output.println("---");
- testRun = new HashMap<>();
- testSuite = new HashMap<>();
+ testRun = new LinkedHashMap<>();
+ testSuite = new LinkedHashMap<>();
tests = new LinkedList<>();
testSuite.put("name", suite.getName());
- testSuite.put("desc", suite.getDescription());
+ testSuite.put("desc", suite.getTextDescription());
+ DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
+ Date date = new Date();
+ testRun.put("date", dateFormat.format(date));
testRun.put("suite", testSuite);
testRun.put("device", deviceObject(suite));
testRun.put("tests", tests);
@@ -41,37 +43,64 @@ public abstract class BaseYAMLTestWriter implements TestWriter {
abstract protected Map<String, Object> deviceObject(TestSuite suite);
- private Map<String, Object> testObject(Test t) {
+ private Object causeObject(Object cause) {
+ if (cause == null) {
+ return null;
+ } else if (cause instanceof Throwable) {
+ StringBuilder sb = new StringBuilder();
+ for (Throwable t = (Throwable) cause; t != null; t = t.getCause()) {
+ sb.append(t.toString());
+ sb.append(System.lineSeparator());
+ }
+ return sb.toString();
+ } else {
+ return cause.toString();
+ }
+ }
+
+ private Map<String, Object> resultObject(Result result) {
+ Map<String, Object> resultObject = new LinkedHashMap<>();
+ resultObject.put("ok", result.ok());
+ resultObject.put("value", result.getValue().name());
+ resultObject.put("cause", causeObject(result.getCause()));
+ return resultObject;
+ }
+
+ private Map<String, Object> testObject(Test t, int index) {
Map<String, Object> testObj;
if (t instanceof CompoundTest) {
CompoundTest test = (CompoundTest) t;
testObj = new HashMap<>();
testObj.put("type", "compound");
List<Map<String, Object>> innerTests = new LinkedList<>();
- for (Test innerTest : test.getTests()) {
- innerTests.add(testObject(innerTest));
+ for (Test innerTest : test.getStartedTests()) {
+ innerTests.add(testObject(innerTest, -1));
}
testObj.put("tests", innerTests);
} else {
- SimpleTest test = (SimpleTest) t;
+ SimpleTest<? extends BaseTestable> test = (SimpleTest<? extends BaseTestable>) t;
testObj = testableObject(test.getTestable());
}
testObj.put("desc", t.getDescription());
- Map<String, Object> result = new HashMap<>();
- result.put("ok", t.ok());
- result.put("value", t.getResultValue().name());
- result.put("cause", t.getResultCause());
- testObj.put("result", result);
+ testObj.put("result", resultObject(t.getResult()));
+ if (index != -1) {
+ testObj.put("index", index);
+ }
return testObj;
}
@Override
- public void outputTest(Test t) {
+ public void outputTest(Test t, int index) {
if (!t.hasRun())
return;
- tests.add(testObject(t));
+ tests.add(testObject(t, index));
+ }
+
+ @Override
+ public void outputError(Test t, Throwable cause, int index) {
+ tests.add(testObject(t, index));
}
@Override
@@ -81,7 +110,7 @@ public abstract class BaseYAMLTestWriter implements TestWriter {
options.setPrettyFlow(true);
Yaml yaml = new Yaml(options);
- Map<String, Object> result = new HashMap<>();
+ Map<String, Object> result = new LinkedHashMap<>();
result.put("testRun", testRun);
String out = yaml.dump(result);
diff --git a/src/cz/crcs/ectester/common/output/TeeTestWriter.java b/src/cz/crcs/ectester/common/output/TeeTestWriter.java
new file mode 100644
index 0000000..58a0a15
--- /dev/null
+++ b/src/cz/crcs/ectester/common/output/TeeTestWriter.java
@@ -0,0 +1,43 @@
+package cz.crcs.ectester.common.output;
+
+import cz.crcs.ectester.common.test.Test;
+import cz.crcs.ectester.common.test.TestSuite;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class TeeTestWriter implements TestWriter {
+ protected TestWriter[] writers;
+
+ public TeeTestWriter(TestWriter... writers) {
+ this.writers = writers;
+ }
+
+ @Override
+ public void begin(TestSuite suite) {
+ for (TestWriter writer : writers) {
+ writer.begin(suite);
+ }
+ }
+
+ @Override
+ public void outputTest(Test t, int index) {
+ for (TestWriter writer : writers) {
+ writer.outputTest(t, index);
+ }
+ }
+
+ @Override
+ public void outputError(Test t, Throwable cause, int index) {
+ for (TestWriter writer : writers) {
+ writer.outputError(t, cause, index);
+ }
+ }
+
+ @Override
+ public void end() {
+ for (TestWriter writer : writers) {
+ writer.end();
+ }
+ }
+}
diff --git a/src/cz/crcs/ectester/common/output/TestWriter.java b/src/cz/crcs/ectester/common/output/TestWriter.java
index 0ecfd5a..eb95804 100644
--- a/src/cz/crcs/ectester/common/output/TestWriter.java
+++ b/src/cz/crcs/ectester/common/output/TestWriter.java
@@ -7,9 +7,33 @@ import cz.crcs.ectester.common.test.TestSuite;
* @author Jan Jancar johny@neuromancer.sk
*/
public interface TestWriter {
+ /**
+ * Begin writing the <code>TestSuite suite</code>.
+ * This should reset all the internal state of the writer
+ * and prepare it to output tests from <code>suite</code>.
+ * It may also write any header part of the output of the
+ * writer but doesn't have to.
+ *
+ * @param suite The <code>TestSuite</code> to start writing.
+ */
void begin(TestSuite suite);
- void outputTest(Test t);
+ /**
+ *
+ * @param t
+ * @param index
+ */
+ void outputTest(Test t, int index);
+ /**
+ * @param t
+ * @param cause
+ * @param index
+ */
+ void outputError(Test t, Throwable cause, int index);
+
+ /**
+ *
+ */
void end();
}
diff --git a/src/cz/crcs/ectester/common/test/BaseTestable.java b/src/cz/crcs/ectester/common/test/BaseTestable.java
index a4b9a00..3c304d9 100644
--- a/src/cz/crcs/ectester/common/test/BaseTestable.java
+++ b/src/cz/crcs/ectester/common/test/BaseTestable.java
@@ -3,10 +3,11 @@ package cz.crcs.ectester.common.test;
/**
* @author Jan Jancar johny@neuromancer.sk
*/
-public abstract class BaseTestable implements Testable {
+public abstract class BaseTestable implements Testable, Cloneable {
protected boolean hasRun;
protected boolean ok;
protected boolean error;
+ protected Object errorCause;
@Override
public boolean hasRun() {
@@ -24,9 +25,20 @@ public abstract class BaseTestable implements Testable {
}
@Override
+ public Object errorCause() {
+ return errorCause;
+ }
+
+ @Override
public void reset() {
hasRun = false;
ok = false;
error = false;
+ errorCause = null;
+ }
+
+ @Override
+ protected BaseTestable clone() throws CloneNotSupportedException {
+ return (BaseTestable) super.clone();
}
}
diff --git a/src/cz/crcs/ectester/common/test/CompoundTest.java b/src/cz/crcs/ectester/common/test/CompoundTest.java
index 10ecf9c..ba4ad4f 100644
--- a/src/cz/crcs/ectester/common/test/CompoundTest.java
+++ b/src/cz/crcs/ectester/common/test/CompoundTest.java
@@ -2,6 +2,7 @@ package cz.crcs.ectester.common.test;
import java.util.Arrays;
import java.util.Objects;
+import java.util.function.Consumer;
import java.util.function.Function;
/**
@@ -9,30 +10,64 @@ import java.util.function.Function;
*
* @author Jan Jancar johny@neuromancer.sk
*/
-public class CompoundTest extends Test {
- private Function<Test[], Result> callback;
+public class CompoundTest extends Test implements Cloneable {
+ private Function<Test[], Result> resultCallback;
+ private Consumer<Test[]> runCallback;
private Test[] tests;
- private String description;
+ private String description = "";
- private CompoundTest(Function<Test[], Result> callback, Test... tests) {
- this.callback = callback;
+ private final static Consumer<Test[]> RUN_ALL = tests -> {
+ for (Test t : tests) {
+ t.run();
+ }
+ };
+
+ private final static Consumer<Test[]> RUN_GREEDY_ALL = tests -> {
+ for (Test t : tests) {
+ t.run();
+ if (!t.ok()) {
+ break;
+ }
+ }
+ };
+
+ private final static Consumer<Test[]> RUN_GREEDY_ANY = tests -> {
+ for (Test t : tests) {
+ t.run();
+ if (t.ok()) {
+ break;
+ }
+ }
+ };
+
+ private CompoundTest(Function<Test[], Result> resultCallback, Consumer<Test[]> runCallback, Test... tests) {
+ this.resultCallback = resultCallback;
+ this.runCallback = runCallback;
this.tests = Arrays.stream(tests).filter(Objects::nonNull).toArray(Test[]::new);
}
- private CompoundTest(Function<Test[], Result> callback, String descripiton, Test... tests) {
- this(callback, tests);
+ private CompoundTest(Function<Test[], Result> callback, Consumer<Test[]> runCallback, String descripiton, Test... tests) {
+ this(callback, runCallback, tests);
this.description = descripiton;
}
public static CompoundTest function(Function<Test[], Result> callback, Test... tests) {
- return new CompoundTest(callback, tests);
+ return new CompoundTest(callback, RUN_ALL, tests);
+ }
+
+ public static CompoundTest function(Function<Test[], Result> callback, Consumer<Test[]> runCallback, Test... tests) {
+ return new CompoundTest(callback, runCallback, tests);
}
public static CompoundTest function(Function<Test[], Result> callback, String description, Test... tests) {
- return new CompoundTest(callback, description, tests);
+ return new CompoundTest(callback, RUN_ALL, description, tests);
}
- public static CompoundTest all(Result.ExpectedValue what, Test... all) {
+ public static CompoundTest function(Function<Test[], Result> callback, Consumer<Test[]> runCallback, String description, Test... tests) {
+ return new CompoundTest(callback, runCallback, description, tests);
+ }
+
+ private static CompoundTest expectAll(Result.ExpectedValue what, Consumer<Test[]> runCallback, Test[] all) {
return new CompoundTest((tests) -> {
for (Test test : tests) {
if (!Result.Value.fromExpected(what, test.ok()).ok()) {
@@ -40,7 +75,11 @@ public class CompoundTest extends Test {
}
}
return new Result(Result.Value.SUCCESS, "All sub-tests had the expected result.");
- }, all);
+ }, runCallback, all);
+ }
+
+ public static CompoundTest all(Result.ExpectedValue what, Test... all) {
+ return expectAll(what, RUN_ALL, all);
}
public static CompoundTest all(Result.ExpectedValue what, String description, Test... all) {
@@ -49,7 +88,47 @@ public class CompoundTest extends Test {
return result;
}
- public static CompoundTest any(Result.ExpectedValue what, Test... any) {
+ public static CompoundTest greedyAll(Result.ExpectedValue what, Test... all) {
+ return expectAll(what, RUN_GREEDY_ALL, all);
+ }
+
+ public static CompoundTest greedyAll(Result.ExpectedValue what, String description, Test... all) {
+ CompoundTest result = CompoundTest.greedyAll(what, all);
+ result.setDescription(description);
+ return result;
+ }
+
+ public static CompoundTest greedyAllTry(Result.ExpectedValue what, Test... all) {
+ return new CompoundTest((tests) -> {
+ int run = 0;
+ int ok = 0;
+ for (Test test : tests) {
+ if (test.hasRun()) {
+ run++;
+ if (Result.Value.fromExpected(what, test.ok()).ok()) {
+ ok++;
+ }
+ }
+ }
+ if (run == tests.length) {
+ if (ok == run) {
+ return new Result(Result.Value.SUCCESS, "All sub-tests had the expected result.");
+ } else {
+ return new Result(Result.Value.FAILURE, "Some sub-tests did not have the expected result.");
+ }
+ } else {
+ return new Result(Result.Value.SUCCESS, "All considered sub-tests had the expected result.");
+ }
+ }, RUN_GREEDY_ALL, all);
+ }
+
+ public static CompoundTest greedyAllTry(Result.ExpectedValue what, String description, Test... all) {
+ CompoundTest result = CompoundTest.greedyAllTry(what, all);
+ result.setDescription(description);
+ return result;
+ }
+
+ private static CompoundTest expectAny(Result.ExpectedValue what, Consumer<Test[]> runCallback, Test[] any) {
return new CompoundTest((tests) -> {
for (Test test : tests) {
if (Result.Value.fromExpected(what, test.ok()).ok()) {
@@ -57,7 +136,21 @@ public class CompoundTest extends Test {
}
}
return new Result(Result.Value.FAILURE, "None of the sub-tests had the expected result.");
- }, any);
+ }, runCallback, any);
+ }
+
+ public static CompoundTest greedyAny(Result.ExpectedValue what, Test... any) {
+ return expectAny(what, RUN_GREEDY_ANY, any);
+ }
+
+ public static CompoundTest greedyAny(Result.ExpectedValue what, String description, Test... any) {
+ CompoundTest result = CompoundTest.greedyAny(what, any);
+ result.setDescription(description);
+ return result;
+ }
+
+ public static CompoundTest any(Result.ExpectedValue what, Test... any) {
+ return expectAny(what, RUN_ALL, any);
}
public static CompoundTest any(Result.ExpectedValue what, String description, Test... any) {
@@ -74,7 +167,7 @@ public class CompoundTest extends Test {
}
}
return new Result(Result.Value.SUCCESS, "All sub-tests matched the expected mask.");
- }, masked);
+ }, RUN_ALL, masked);
}
public static CompoundTest mask(Result.ExpectedValue[] results, String description, Test... masked) {
@@ -84,20 +177,25 @@ public class CompoundTest extends Test {
}
public Test[] getTests() {
- return tests;
+ return tests.clone();
}
- @Override
- public void run() throws TestException {
- if (hasRun)
- return;
+ public Test[] getRunTests() {
+ return Arrays.stream(tests).filter(Test::hasRun).toArray(Test[]::new);
+ }
- for (Test test : tests) {
- test.run();
- }
+ public Test[] getStartedTests() {
+ return Arrays.stream(tests).filter(Test::hasStarted).toArray(Test[]::new);
+ }
- result = callback.apply(tests);
- this.hasRun = true;
+ public Test[] getSkippedTests() {
+ return Arrays.stream(tests).filter((test) -> !test.hasRun()).toArray(Test[]::new);
+ }
+
+ @Override
+ protected void runSelf() {
+ runCallback.accept(tests);
+ result = resultCallback.apply(tests);
}
public void setDescription(String description) {
@@ -108,4 +206,9 @@ public class CompoundTest extends Test {
public String getDescription() {
return description;
}
+
+ @Override
+ public CompoundTest clone() throws CloneNotSupportedException {
+ return (CompoundTest) super.clone();
+ }
}
diff --git a/src/cz/crcs/ectester/common/test/Result.java b/src/cz/crcs/ectester/common/test/Result.java
index 11fcb4d..f065f9c 100644
--- a/src/cz/crcs/ectester/common/test/Result.java
+++ b/src/cz/crcs/ectester/common/test/Result.java
@@ -8,13 +8,13 @@ package cz.crcs.ectester.common.test;
public class Result {
private Value value;
- private String cause;
+ private Object cause;
public Result(Value value) {
this.value = value;
}
- public Result(Value value, String cause) {
+ public Result(Value value, Object cause) {
this(value);
this.cause = cause;
}
@@ -23,7 +23,7 @@ public class Result {
return value;
}
- public String getCause() {
+ public Object getCause() {
return cause;
}
@@ -49,18 +49,24 @@ public class Result {
* A result value of a Test.
*/
public enum Value {
- SUCCESS(true),
- FAILURE(false),
- UXSUCCESS(false),
- XFAILURE(true),
- ERROR(false);
+ SUCCESS(true, "Expected success."),
+ FAILURE(false, "Unexpected failure."),
+ UXSUCCESS(false, "Unexpected success."),
+ XFAILURE(true, "Expected failure."),
+ ERROR(false, "Error.");
private boolean ok;
+ private String desc;
Value(boolean ok) {
this.ok = ok;
}
+ Value(boolean ok, String desc) {
+ this(ok);
+ this.desc = desc;
+ }
+
public static Value fromExpected(ExpectedValue expected, boolean successful) {
switch (expected) {
case SUCCESS:
@@ -68,7 +74,7 @@ public class Result {
case FAILURE:
return successful ? UXSUCCESS : XFAILURE;
case ANY:
- return SUCCESS;
+ return successful ? SUCCESS : XFAILURE;
}
return SUCCESS;
}
@@ -83,6 +89,10 @@ public class Result {
public boolean ok() {
return ok;
}
+
+ public String description() {
+ return desc;
+ }
}
/**
diff --git a/src/cz/crcs/ectester/common/test/SimpleTest.java b/src/cz/crcs/ectester/common/test/SimpleTest.java
index f68320a..d2b3e94 100644
--- a/src/cz/crcs/ectester/common/test/SimpleTest.java
+++ b/src/cz/crcs/ectester/common/test/SimpleTest.java
@@ -4,11 +4,17 @@ package cz.crcs.ectester.common.test;
* @param <T>
* @author Jan Jancar johny@neuromancer.sk
*/
-public abstract class SimpleTest<T extends BaseTestable> extends Test {
+public abstract class SimpleTest<T extends BaseTestable> extends Test implements Testable {
protected T testable;
protected TestCallback<T> callback;
public SimpleTest(T testable, TestCallback<T> callback) {
+ if (testable == null) {
+ throw new IllegalArgumentException("testable is null.");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("callback is null.");
+ }
this.testable = testable;
this.callback = callback;
}
@@ -16,4 +22,17 @@ public abstract class SimpleTest<T extends BaseTestable> extends Test {
public T getTestable() {
return testable;
}
+
+ @Override
+ protected void runSelf() {
+ testable.run();
+ result = callback.apply(testable);
+ }
+
+ @Override
+ public SimpleTest clone() throws CloneNotSupportedException {
+ SimpleTest clone = (SimpleTest) super.clone();
+ clone.testable = testable.clone();
+ return clone;
+ }
}
diff --git a/src/cz/crcs/ectester/common/test/Test.java b/src/cz/crcs/ectester/common/test/Test.java
index 3d0baf6..8bf9502 100644
--- a/src/cz/crcs/ectester/common/test/Test.java
+++ b/src/cz/crcs/ectester/common/test/Test.java
@@ -7,33 +7,17 @@ import static cz.crcs.ectester.common.test.Result.Value;
*
* @author Jan Jancar johny@neuromancer.sk
*/
-public abstract class Test implements Testable {
+public abstract class Test implements Testable, Cloneable {
protected boolean hasRun;
+ protected boolean hasStarted;
protected Result result;
public Result getResult() {
- if (!hasRun) {
- return null;
- }
return result;
}
- public Value getResultValue() {
- if (!hasRun) {
- return null;
- }
- return result.getValue();
- }
-
- public String getResultCause() {
- if (!hasRun) {
- return null;
- }
- return result.getCause();
- }
-
public boolean ok() {
- if (!hasRun) {
+ if (result == null) {
return true;
}
return result.ok();
@@ -41,26 +25,59 @@ public abstract class Test implements Testable {
@Override
public boolean error() {
- if (!hasRun) {
+ if (result == null) {
return false;
}
return result.compareTo(Value.ERROR);
}
@Override
+ public Object errorCause() {
+ if (result == null || !result.compareTo(Value.ERROR)) {
+ return null;
+ }
+ return result.getCause();
+ }
+
+ @Override
public boolean hasRun() {
return hasRun;
}
+ public boolean hasStarted() {
+ return hasStarted;
+ }
+
@Override
public void reset() {
hasRun = false;
+ hasStarted = false;
result = null;
}
public abstract String getDescription();
@Override
- public abstract void run() throws TestException;
+ public Test clone() throws CloneNotSupportedException {
+ return (Test) super.clone();
+ }
+
+ @Override
+ public void run() {
+ if (hasRun)
+ return;
+ try {
+ hasStarted = true;
+ runSelf();
+ hasRun = true;
+ } catch (TestException e) {
+ result = new Result(Value.ERROR, e);
+ throw e;
+ } catch (Exception e) {
+ result = new Result(Value.ERROR, e);
+ throw new TestException(e);
+ }
+ }
+ protected abstract void runSelf();
}
diff --git a/src/cz/crcs/ectester/common/test/TestException.java b/src/cz/crcs/ectester/common/test/TestException.java
index 008e9f6..291a073 100644
--- a/src/cz/crcs/ectester/common/test/TestException.java
+++ b/src/cz/crcs/ectester/common/test/TestException.java
@@ -2,11 +2,12 @@ package cz.crcs.ectester.common.test;
/**
* A TestException is an Exception that can be thrown during the running of a Testable,
- * or a TestSuite. It means that the Testable/TestSuite encountered an unexpected error
- * during it's run which points to an error in ECTester or it's runtime environment.cd
+ * or a Test. It means that the Testable/TestSuite encountered an unexpected error
+ * and has to terminate.
+ *
* @author Jan Jancar johny@neuromancer.sk
*/
-public class TestException extends Exception {
+public class TestException extends RuntimeException {
public TestException(Throwable e) {
super(e);
}
diff --git a/src/cz/crcs/ectester/common/test/TestSuite.java b/src/cz/crcs/ectester/common/test/TestSuite.java
index f4f30ee..b12680a 100644
--- a/src/cz/crcs/ectester/common/test/TestSuite.java
+++ b/src/cz/crcs/ectester/common/test/TestSuite.java
@@ -1,56 +1,100 @@
package cz.crcs.ectester.common.test;
import cz.crcs.ectester.common.output.TestWriter;
-import cz.crcs.ectester.data.EC_Store;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.stream.Collectors;
/**
* @author Jan Jancar johny@neuromancer.sk
*/
public abstract class TestSuite {
protected String name;
- protected String description;
- protected TestWriter writer;
+ protected String[] description;
+ private TestWriter writer;
+ private Test running;
+ private int ran = 0;
+ private int runFrom = 0;
+ private int runTo = -1;
- public TestSuite(TestWriter writer, String name, String description) {
+ public TestSuite(TestWriter writer, String name, String... description) {
this.writer = writer;
this.name = name;
this.description = description;
}
- public void run() throws TestException {
+ /**
+ * Run the <code>TestSuite</code>.
+ */
+ public void run() {
+ run(0);
+ }
+
+ public void run(int from) {
+ run(from, -1);
+ }
+
+ public void run(int from, int to) {
+ this.runFrom = from;
+ this.runTo = to;
writer.begin(this);
try {
runTests();
+ } catch (TestException e) {
+ writer.outputError(running, e, ran);
} catch (Exception e) {
- throw new TestException(e);
+ writer.end();
+ throw new TestSuiteException(e);
}
writer.end();
}
- protected Test runTest(Test t) throws TestException {
+ /**
+ * Run the given test and return it back.
+ *
+ * @param t The test to run.
+ * @return The test that was run.
+ * @throws TestException
+ */
+ protected <T extends Test> T runTest(T t) {
+ running = t;
t.run();
+ running = null;
return t;
}
- protected Test doTest(Test t) throws TestException {
- t.run();
- writer.outputTest(t);
+ /**
+ * Run the given test, output it and return it back.
+ *
+ * @param t The test to run.
+ * @return The test that was run.
+ * @throws TestException
+ */
+ protected <T extends Test> T doTest(T t) {
+ if (ran >= runFrom && (runTo < 0 || ran <= runTo)) {
+ runTest(t);
+ writer.outputTest(t, ran);
+ }
+ ran++;
return t;
}
+ /**
+ *
+ */
protected abstract void runTests() throws Exception;
public String getName() {
return name;
}
- public String getDescription() {
+ public String[] getDescription() {
return description;
}
+ public String getTextDescription() {
+ return String.join(System.lineSeparator(), description);
+ }
+
+ public String toString() {
+ return null;
+ }
+
}
diff --git a/src/cz/crcs/ectester/common/test/TestSuiteException.java b/src/cz/crcs/ectester/common/test/TestSuiteException.java
new file mode 100644
index 0000000..cc3cfda
--- /dev/null
+++ b/src/cz/crcs/ectester/common/test/TestSuiteException.java
@@ -0,0 +1,13 @@
+package cz.crcs.ectester.common.test;
+
+/**
+ * An unexpected exception was thrown while running a TestSuite, outside Test
+ * or a Testable.
+ *
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class TestSuiteException extends RuntimeException {
+ public TestSuiteException(Throwable e) {
+ super(e);
+ }
+}
diff --git a/src/cz/crcs/ectester/common/test/Testable.java b/src/cz/crcs/ectester/common/test/Testable.java
index 33c9485..7b4545c 100644
--- a/src/cz/crcs/ectester/common/test/Testable.java
+++ b/src/cz/crcs/ectester/common/test/Testable.java
@@ -15,6 +15,11 @@ public interface Testable {
boolean error();
/**
+ * @return The cause of an error, if it happened, otherwise null.
+ */
+ Object errorCause();
+
+ /**
* @return Whether this runnable was run.
*/
boolean hasRun();
@@ -29,5 +34,5 @@ public interface Testable {
*
* @throws TestException If an unexpected exception/error is encountered.
*/
- void run() throws TestException;
+ void run();
}
diff --git a/src/cz/crcs/ectester/common/util/ByteUtil.java b/src/cz/crcs/ectester/common/util/ByteUtil.java
index 90c6eaa..daacabb 100644
--- a/src/cz/crcs/ectester/common/util/ByteUtil.java
+++ b/src/cz/crcs/ectester/common/util/ByteUtil.java
@@ -7,15 +7,27 @@ package cz.crcs.ectester.common.util;
* @author Jan Jancar johny@neuromancer.sk
*/
public class ByteUtil {
+
+ /**
+ * Gen a short from a byte array at <code>offset</code>, big-endian.
+ * @return the short value
+ */
public static short getShort(byte[] array, int offset) {
return (short) (((array[offset] & 0xFF) << 8) | (array[offset + 1] & 0xFF));
}
+ /**
+ * Set a short in a byte array at <code>offset</code>, big-endian.
+ */
public static void setShort(byte[] array, int offset, short value) {
array[offset + 1] = (byte) (value & 0xFF);
array[offset] = (byte) ((value >> 8) & 0xFF);
}
+ /**
+ * Compare two byte arrays upto <code>length</code> and get first difference.
+ * @return the position of the first difference in the two byte arrays, or <code>length</code> if they are equal.
+ */
public static int diffBytes(byte[] one, int oneOffset, byte[] other, int otherOffset, int length) {
for (int i = 0; i < length; ++i) {
byte a = one[i + oneOffset];
@@ -27,10 +39,17 @@ public class ByteUtil {
return length;
}
+ /**
+ * Compare two byte arrays, upto <code>length</code>.
+ * @return whether the arrays are equal upto <code>length</code>
+ */
public static boolean compareBytes(byte[] one, int oneOffset, byte[] other, int otherOffset, int length) {
return diffBytes(one, oneOffset, other, otherOffset, length) == length;
}
+ /**
+ * Test if the byte array has all values equal to <code>value</code>.
+ */
public static boolean allValue(byte[] array, byte value) {
for (byte a : array) {
if (a != value)
@@ -39,10 +58,38 @@ public class ByteUtil {
return true;
}
+ public static byte[] shortToBytes(short value) {
+ byte[] result = new byte[2];
+ setShort(result, 0, value);
+ return result;
+ }
+
+ public static byte[] shortToBytes(short[] shorts) {
+ if (shorts == null) {
+ return null;
+ }
+ byte[] result = new byte[shorts.length * 2];
+ for (int i = 0; i < shorts.length; ++i) {
+ setShort(result, 2 * i, shorts[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Parse a hex string into a byte array, big-endian.
+ * @param hex The String to parse.
+ * @return the byte array from the hex string.
+ */
public static byte[] hexToBytes(String hex) {
return hexToBytes(hex, true);
}
+ /**
+ * Parse a hex string into a byte-array, specify endianity.
+ * @param hex The String to parse.
+ * @param bigEndian Whether to parse as big-endian.
+ * @return the byte array from the hex string.
+ */
public static byte[] hexToBytes(String hex, boolean bigEndian) {
hex = hex.replace(" ", "");
int len = hex.length();
@@ -125,4 +172,8 @@ public class ByteUtil {
}
return out;
}
+
+ public static byte[] prependLength(byte[] data) {
+ return concatenate(ByteUtil.shortToBytes((short) data.length), data);
+ }
}
diff --git a/src/cz/crcs/ectester/common/util/CardUtil.java b/src/cz/crcs/ectester/common/util/CardUtil.java
index 8285d8b..a628d5b 100644
--- a/src/cz/crcs/ectester/common/util/CardUtil.java
+++ b/src/cz/crcs/ectester/common/util/CardUtil.java
@@ -4,8 +4,10 @@ import cz.crcs.ectester.applet.ECTesterApplet;
import cz.crcs.ectester.applet.EC_Consts;
import javacard.framework.ISO7816;
import javacard.security.CryptoException;
+import javacard.security.KeyPair;
-import static cz.crcs.ectester.applet.ECTesterApplet.*;
+import java.util.LinkedList;
+import java.util.List;
/**
* @author Petr Svenda petr@svenda.com
@@ -15,13 +17,19 @@ public class CardUtil {
public static byte getKA(String name) {
switch (name) {
case "DH":
- case "ECDH":
- return ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
case "DHC":
- case "ECDHC":
- return ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DHC;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC;
+ case "DH_PLAIN":
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN;
+ case "DHC_PLAIN":
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC_PLAIN;
+ case "PACE_GM":
+ return EC_Consts.KeyAgreement_ALG_EC_PACE_GM;
+ case "DH_PLAIN_XY":
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY;
default:
- return ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
}
}
@@ -70,75 +78,102 @@ public class CardUtil {
}
public static String getSW(short sw) {
- switch (sw) {
- case ISO7816.SW_APPLET_SELECT_FAILED:
- return "APPLET_SELECT_FAILED";
- case ISO7816.SW_BYTES_REMAINING_00:
- return "BYTES_REMAINING";
- case ISO7816.SW_CLA_NOT_SUPPORTED:
- return "CLA_NOT_SUPPORTED";
- case ISO7816.SW_COMMAND_NOT_ALLOWED:
- return "COMMAND_NOT_ALLOWED";
- case ISO7816.SW_CONDITIONS_NOT_SATISFIED:
- return "CONDITIONS_NOT_SATISFIED";
- case ISO7816.SW_CORRECT_LENGTH_00:
- return "CORRECT_LENGTH";
- case ISO7816.SW_DATA_INVALID:
- return "DATA_INVALID";
- case ISO7816.SW_FILE_FULL:
- return "FILE_FULL";
- case ISO7816.SW_FILE_INVALID:
- return "FILE_INVALID";
- case ISO7816.SW_FILE_NOT_FOUND:
- return "FILE_NOT_FOUND";
- case ISO7816.SW_FUNC_NOT_SUPPORTED:
- return "FUNC_NOT_SUPPORTED";
- case ISO7816.SW_INCORRECT_P1P2:
- return "INCORRECT_P1P2";
- case ISO7816.SW_INS_NOT_SUPPORTED:
- return "INS_NOT_SUPPORTED";
- case ISO7816.SW_LOGICAL_CHANNEL_NOT_SUPPORTED:
- return "LOGICAL_CHANNEL_NOT_SUPPORTED";
- case ISO7816.SW_RECORD_NOT_FOUND:
- return "RECORD_NOT_FOUND";
- case ISO7816.SW_SECURE_MESSAGING_NOT_SUPPORTED:
- return "SECURE_MESSAGING_NOT_SUPPORTED";
- case ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED:
- return "SECURITY_STATUS_NOT_SATISFIED";
- case ISO7816.SW_UNKNOWN:
- return "UNKNOWN";
- case ISO7816.SW_WARNING_STATE_UNCHANGED:
- return "WARNING_STATE_UNCHANGED";
- case ISO7816.SW_WRONG_DATA:
- return "WRONG_DATA";
- case ISO7816.SW_WRONG_LENGTH:
- return "WRONG_LENGTH";
- case ISO7816.SW_WRONG_P1P2:
- return "WRONG_P1P2";
- case CryptoException.ILLEGAL_VALUE:
- return "ILLEGAL_VALUE";
- case CryptoException.UNINITIALIZED_KEY:
- return "UNINITIALIZED_KEY";
- case CryptoException.NO_SUCH_ALGORITHM:
- return "NO_SUCH_ALG";
- case CryptoException.INVALID_INIT:
- return "INVALID_INIT";
- case CryptoException.ILLEGAL_USE:
- return "ILLEGAL_USE";
- case ECTesterApplet.SW_SIG_VERIFY_FAIL:
- return "SIG_VERIFY_FAIL";
- case ECTesterApplet.SW_DH_DHC_MISMATCH:
- return "DH_DHC_MISMATCH";
- case ECTesterApplet.SW_KEYPAIR_NULL:
- return "KEYPAIR_NULL";
- case ECTesterApplet.SW_KA_NULL:
- return "KA_NULL";
- case ECTesterApplet.SW_SIGNATURE_NULL:
- return "SIGNATURE_NULL";
- case ECTesterApplet.SW_OBJECT_NULL:
- return "OBJECT_NULL";
+ int upper = (sw & 0xff00) >> 8;
+ int lower = (sw & 0xff);
+ switch (upper) {
+ case 0xf1:
+ return String.format("CryptoException(%d)", lower);
+ case 0xf2:
+ return String.format("SystemException(%d)", lower);
+ case 0xf3:
+ return String.format("PINException(%d)", lower);
+ case 0xf4:
+ return String.format("TransactionException(%d)", lower);
+ case 0xf5:
+ return String.format("CardRuntimeException(%d)", lower);
default:
- return "unknown";
+ switch (sw) {
+ case ISO7816.SW_APPLET_SELECT_FAILED:
+ return "APPLET_SELECT_FAILED";
+ case ISO7816.SW_BYTES_REMAINING_00:
+ return "BYTES_REMAINING";
+ case ISO7816.SW_CLA_NOT_SUPPORTED:
+ return "CLA_NOT_SUPPORTED";
+ case ISO7816.SW_COMMAND_NOT_ALLOWED:
+ return "COMMAND_NOT_ALLOWED";
+ case ISO7816.SW_CONDITIONS_NOT_SATISFIED:
+ return "CONDITIONS_NOT_SATISFIED";
+ case ISO7816.SW_CORRECT_LENGTH_00:
+ return "CORRECT_LENGTH";
+ case ISO7816.SW_DATA_INVALID:
+ return "DATA_INVALID";
+ case ISO7816.SW_FILE_FULL:
+ return "FILE_FULL";
+ case ISO7816.SW_FILE_INVALID:
+ return "FILE_INVALID";
+ case ISO7816.SW_FILE_NOT_FOUND:
+ return "FILE_NOT_FOUND";
+ case ISO7816.SW_FUNC_NOT_SUPPORTED:
+ return "FUNC_NOT_SUPPORTED";
+ case ISO7816.SW_INCORRECT_P1P2:
+ return "INCORRECT_P1P2";
+ case ISO7816.SW_INS_NOT_SUPPORTED:
+ return "INS_NOT_SUPPORTED";
+ case ISO7816.SW_LOGICAL_CHANNEL_NOT_SUPPORTED:
+ return "LOGICAL_CHANNEL_NOT_SUPPORTED";
+ case ISO7816.SW_RECORD_NOT_FOUND:
+ return "RECORD_NOT_FOUND";
+ case ISO7816.SW_SECURE_MESSAGING_NOT_SUPPORTED:
+ return "SECURE_MESSAGING_NOT_SUPPORTED";
+ case ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED:
+ return "SECURITY_STATUS_NOT_SATISFIED";
+ case ISO7816.SW_UNKNOWN:
+ return "UNKNOWN";
+ case ISO7816.SW_WARNING_STATE_UNCHANGED:
+ return "WARNING_STATE_UNCHANGED";
+ case ISO7816.SW_WRONG_DATA:
+ return "WRONG_DATA";
+ case ISO7816.SW_WRONG_LENGTH:
+ return "WRONG_LENGTH";
+ case ISO7816.SW_WRONG_P1P2:
+ return "WRONG_P1P2";
+ case CryptoException.ILLEGAL_VALUE:
+ return "ILLEGAL_VALUE";
+ case CryptoException.UNINITIALIZED_KEY:
+ return "UNINITIALIZED_KEY";
+ case CryptoException.NO_SUCH_ALGORITHM:
+ return "NO_SUCH_ALG";
+ case CryptoException.INVALID_INIT:
+ return "INVALID_INIT";
+ case CryptoException.ILLEGAL_USE:
+ return "ILLEGAL_USE";
+ case ECTesterApplet.SW_SIG_VERIFY_FAIL:
+ return "SIG_VERIFY_FAIL";
+ case ECTesterApplet.SW_DH_DHC_MISMATCH:
+ return "DH_DHC_MISMATCH";
+ case ECTesterApplet.SW_KEYPAIR_NULL:
+ return "KEYPAIR_NULL";
+ case ECTesterApplet.SW_KA_NULL:
+ return "KA_NULL";
+ case ECTesterApplet.SW_SIGNATURE_NULL:
+ return "SIGNATURE_NULL";
+ case ECTesterApplet.SW_OBJECT_NULL:
+ return "OBJECT_NULL";
+ case ECTesterApplet.SW_Exception:
+ return "Exception";
+ case ECTesterApplet.SW_ArrayIndexOutOfBoundsException:
+ return "ArrayIndexOutOfBoundsException";
+ case ECTesterApplet.SW_ArithmeticException:
+ return "ArithmeticException";
+ case ECTesterApplet.SW_ArrayStoreException:
+ return "ArrayStoreException";
+ case ECTesterApplet.SW_NullPointerException:
+ return "NullPointerException";
+ case ECTesterApplet.SW_NegativeArraySizeException:
+ return "NegativeArraySizeException";
+ default:
+ return "unknown";
+ }
}
}
@@ -151,46 +186,122 @@ public class CardUtil {
}
}
- public static String getCorruption(short corruptionType) {
- switch (corruptionType) {
- case EC_Consts.CORRUPTION_NONE:
- return "NONE";
- case EC_Consts.CORRUPTION_FIXED:
- return "FIXED";
- case EC_Consts.CORRUPTION_ONE:
- return "ONE";
- case EC_Consts.CORRUPTION_ZERO:
- return "ZERO";
- case EC_Consts.CORRUPTION_ONEBYTERANDOM:
- return "ONE_BYTE_RANDOM";
- case EC_Consts.CORRUPTION_FULLRANDOM:
- return "FULL_RANDOM";
- case EC_Consts.CORRUPTION_INCREMENT:
- return "INCREMENT";
- case EC_Consts.CORRUPTION_INFINITY:
- return "INFINITY";
- case EC_Consts.CORRUPTION_COMPRESS:
- return "COMPRESSED";
- case EC_Consts.CORRUPTION_MAX:
- return "MAX";
- default:
- return "unknown";
+ public static String getParams(short params) {
+ if (params == 0) {
+ return "";
+ }
+ List<String> ps = new LinkedList<>();
+ short paramMask = EC_Consts.PARAMETER_FP;
+ while (paramMask <= EC_Consts.PARAMETER_S) {
+ short paramValue = (short) (paramMask & params);
+ if (paramValue != 0) {
+ switch (paramValue) {
+ case EC_Consts.PARAMETER_FP:
+ ps.add("P");
+ break;
+ case EC_Consts.PARAMETER_F2M:
+ ps.add("2^M");
+ break;
+ case EC_Consts.PARAMETER_A:
+ ps.add("A");
+ break;
+ case EC_Consts.PARAMETER_B:
+ ps.add("B");
+ break;
+ case EC_Consts.PARAMETER_G:
+ ps.add("G");
+ break;
+ case EC_Consts.PARAMETER_R:
+ ps.add("R");
+ break;
+ case EC_Consts.PARAMETER_K:
+ ps.add("K");
+ break;
+ case EC_Consts.PARAMETER_W:
+ ps.add("W");
+ break;
+ case EC_Consts.PARAMETER_S:
+ ps.add("S");
+ break;
+ }
+ }
+ paramMask = (short) (paramMask << 1);
+ }
+
+ if (ps.size() != 0) {
+ return "[" + String.join(",", ps) + "]";
+ } else {
+ return "unknown";
+ }
+ }
+
+ public static String getTransformation(short transformationType) {
+ if (transformationType == 0) {
+ return "NONE";
+ }
+ List<String> names = new LinkedList<>();
+ short transformationMask = 1;
+ while (transformationMask <= EC_Consts.TRANSFORMATION_04_MASK) {
+ short transformationValue = (short) (transformationMask & transformationType);
+ if (transformationValue != 0) {
+ switch (transformationValue) {
+ case EC_Consts.TRANSFORMATION_FIXED:
+ names.add("FIXED");
+ break;
+ case EC_Consts.TRANSFORMATION_ONE:
+ names.add("ONE");
+ break;
+ case EC_Consts.TRANSFORMATION_ZERO:
+ names.add("ZERO");
+ break;
+ case EC_Consts.TRANSFORMATION_ONEBYTERANDOM:
+ names.add("ONE_BYTE_RANDOM");
+ break;
+ case EC_Consts.TRANSFORMATION_FULLRANDOM:
+ names.add("FULL_RANDOM");
+ break;
+ case EC_Consts.TRANSFORMATION_INCREMENT:
+ names.add("INCREMENT");
+ break;
+ case EC_Consts.TRANSFORMATION_INFINITY:
+ names.add("INFINITY");
+ break;
+ case EC_Consts.TRANSFORMATION_COMPRESS:
+ names.add("COMPRESSED");
+ break;
+ case EC_Consts.TRANSFORMATION_COMPRESS_HYBRID:
+ names.add("HYBRID");
+ break;
+ case EC_Consts.TRANSFORMATION_04_MASK:
+ names.add("MASK(O4)");
+ break;
+ case EC_Consts.TRANSFORMATION_MAX:
+ names.add("MAX");
+ break;
+ }
+ }
+ transformationMask = (short) ((transformationMask) << 1);
+ }
+ if (names.size() != 0) {
+ return String.join(" + ", names);
+ } else {
+ return "unknown";
}
}
public static String getKATypeString(byte kaType) {
switch (kaType) {
- case KeyAgreement_ALG_EC_SVDP_DH:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DH:
return "ALG_EC_SVDP_DH";
- case KeyAgreement_ALG_EC_SVDP_DH_PLAIN:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN:
return "ALG_EC_SVDP_DH_PLAIN";
- case KeyAgreement_ALG_EC_PACE_GM:
+ case EC_Consts.KeyAgreement_ALG_EC_PACE_GM:
return "ALG_EC_PACE_GM";
- case KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY:
return "ALG_EC_SVDP_DH_PLAIN_XY";
- case KeyAgreement_ALG_EC_SVDP_DHC:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC:
return "ALG_EC_SVDP_DHC";
- case KeyAgreement_ALG_EC_SVDP_DHC_PLAIN:
+ case EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC_PLAIN:
return "ALG_EC_SVDP_DHC_PLAIN";
default:
return "unknown";
@@ -200,17 +311,17 @@ public class CardUtil {
public static byte getKAType(String kaTypeString) {
switch (kaTypeString) {
case "ALG_EC_SVDP_DH":
- return KeyAgreement_ALG_EC_SVDP_DH;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
case "ALG_EC_SVDP_DH_PLAIN":
- return KeyAgreement_ALG_EC_SVDP_DH_PLAIN;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN;
case "ALG_EC_PACE_GM":
- return KeyAgreement_ALG_EC_PACE_GM;
+ return EC_Consts.KeyAgreement_ALG_EC_PACE_GM;
case "ALG_EC_SVDP_DH_PLAIN_XY":
- return KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN_XY;
case "ALG_EC_SVDP_DHC":
- return KeyAgreement_ALG_EC_SVDP_DHC;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC;
case "ALG_EC_SVDP_DHC_PLAIN":
- return KeyAgreement_ALG_EC_SVDP_DHC_PLAIN;
+ return EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC_PLAIN;
default:
return 0;
}
@@ -228,15 +339,15 @@ public class CardUtil {
public static String getSigTypeString(byte sigType) {
switch (sigType) {
- case Signature_ALG_ECDSA_SHA:
+ case EC_Consts.Signature_ALG_ECDSA_SHA:
return "ALG_ECDSA_SHA";
- case Signature_ALG_ECDSA_SHA_224:
+ case EC_Consts.Signature_ALG_ECDSA_SHA_224:
return "ALG_ECDSA_SHA_224";
- case Signature_ALG_ECDSA_SHA_256:
+ case EC_Consts.Signature_ALG_ECDSA_SHA_256:
return "ALG_ECDSA_SHA_256";
- case Signature_ALG_ECDSA_SHA_384:
+ case EC_Consts.Signature_ALG_ECDSA_SHA_384:
return "ALG_ECDSA_SHA_384";
- case Signature_ALG_ECDSA_SHA_512:
+ case EC_Consts.Signature_ALG_ECDSA_SHA_512:
return "ALG_ECDSA_SHA_512";
default:
return "unknown";
@@ -246,15 +357,15 @@ public class CardUtil {
public static byte getSigType(String sigTypeString) {
switch (sigTypeString) {
case "ALG_ECDSA_SHA":
- return Signature_ALG_ECDSA_SHA;
+ return EC_Consts.Signature_ALG_ECDSA_SHA;
case "ALG_ECDSA_SHA_224":
- return Signature_ALG_ECDSA_SHA_224;
+ return EC_Consts.Signature_ALG_ECDSA_SHA_224;
case "ALG_ECDSA_SHA_256":
- return Signature_ALG_ECDSA_SHA_256;
+ return EC_Consts.Signature_ALG_ECDSA_SHA_256;
case "ALG_ECDSA_SHA_384":
- return Signature_ALG_ECDSA_SHA_384;
+ return EC_Consts.Signature_ALG_ECDSA_SHA_384;
case "ALG_ECDSA_SHA_512":
- return Signature_ALG_ECDSA_SHA_512;
+ return EC_Consts.Signature_ALG_ECDSA_SHA_512;
default:
return 0;
}
@@ -269,4 +380,31 @@ public class CardUtil {
}
return sigType;
}
+
+ public static String getKeyTypeString(byte keyClass) {
+ switch (keyClass) {
+ case KeyPair.ALG_EC_FP:
+ return "ALG_EC_FP";
+ case KeyPair.ALG_EC_F2M:
+ return "ALG_EC_F2M";
+ default:
+ return "";
+ }
+ }
+
+ public static String getParameterString(short params) {
+ String what = "";
+ if (params == EC_Consts.PARAMETERS_DOMAIN_F2M || params == EC_Consts.PARAMETERS_DOMAIN_FP) {
+ what = "curve";
+ } else if (params == EC_Consts.PARAMETER_W) {
+ what = "pubkey";
+ } else if (params == EC_Consts.PARAMETER_S) {
+ what = "privkey";
+ } else if (params == EC_Consts.PARAMETERS_KEYPAIR) {
+ what = "keypair";
+ } else {
+ what = getParams(params);
+ }
+ return what;
+ }
}
diff --git a/src/cz/crcs/ectester/common/util/ECUtil.java b/src/cz/crcs/ectester/common/util/ECUtil.java
index 973b813..0979d91 100644
--- a/src/cz/crcs/ectester/common/util/ECUtil.java
+++ b/src/cz/crcs/ectester/common/util/ECUtil.java
@@ -146,16 +146,22 @@ public class ECUtil {
alpha = alpha.add(x.multiply(a));
alpha = alpha.add(b);
+ if(!isResidue(alpha, p)) {
+ throw new IllegalArgumentException();
+ }
+
BigInteger beta = modSqrt(alpha, p);
if (beta.getLowestSetBit() == 0) {
// rightmost bit is one
if (data[0] == 0x02) {
- beta = beta.negate();
+ // yp is 0
+ beta = p.subtract(beta);
}
} else {
// rightmost bit is zero
if (data[0] == 0x03) {
- beta = beta.negate();
+ // yp is 1
+ beta = p.subtract(beta);
}
}
diff --git a/src/cz/crcs/ectester/common/util/FileUtil.java b/src/cz/crcs/ectester/common/util/FileUtil.java
new file mode 100644
index 0000000..790596b
--- /dev/null
+++ b/src/cz/crcs/ectester/common/util/FileUtil.java
@@ -0,0 +1,33 @@
+package cz.crcs.ectester.common.util;
+
+import cz.crcs.ectester.common.output.TeeOutputStream;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class FileUtil {
+ public static OutputStream openStream(String[] files) throws FileNotFoundException {
+ if (files == null) {
+ return null;
+ }
+ List<OutputStream> outs = new LinkedList<>();
+ for (String fileOut : files) {
+ outs.add(new FileOutputStream(fileOut));
+ }
+ return new TeeOutputStream(outs.toArray(new OutputStream[0]));
+ }
+
+ public static OutputStreamWriter openFiles(String[] files) throws FileNotFoundException {
+ if (files == null) {
+ return null;
+ }
+ return new OutputStreamWriter(openStream(files));
+ }
+}
diff --git a/src/cz/crcs/ectester/data/EC_Store.java b/src/cz/crcs/ectester/data/EC_Store.java
index e4ba40c..cb65402 100644
--- a/src/cz/crcs/ectester/data/EC_Store.java
+++ b/src/cz/crcs/ectester/data/EC_Store.java
@@ -21,9 +21,8 @@ import javax.xml.validation.SchemaFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Collections;
-import java.util.Map;
-import java.util.TreeMap;
+import java.util.*;
+import java.util.function.Function;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -42,6 +41,7 @@ public class EC_Store {
dbf.setSchema(sch);
dbf.setNamespaceAware(true);
dbf.setIgnoringComments(true);
+ dbf.setXIncludeAware(true);
dbf.setIgnoringElementContentWhitespace(true);
db = dbf.newDocumentBuilder();
db.setErrorHandler(new ErrorHandler() {
@@ -153,7 +153,7 @@ public class EC_Store {
InputStream csv = parseDataElement(dir, curveElem);
if (!curve.readCSV(csv)) {
- throw new IOException("Invalid csv data.");
+ throw new IOException("Invalid csv data." + id.getTextContent());
}
csv.close();
@@ -219,7 +219,7 @@ public class EC_Store {
InputStream csv = parseDataElement(dir, elem);
if (!kaResult.readCSV(csv)) {
- throw new IOException("Invalid csv data.");
+ throw new IOException("Invalid csv data. " + id.getTextContent());
}
csv.close();
@@ -257,7 +257,7 @@ public class EC_Store {
InputStream csv = parseDataElement(dir, elem);
if (!result.readCSV(csv)) {
- throw new IOException("Invalid CSV data.");
+ throw new IOException("Invalid CSV data. " + id.getTextContent());
}
csv.close();
@@ -319,6 +319,48 @@ public class EC_Store {
return getObject(objClass, query.substring(0, split), query.substring(split + 1));
}
+ private static <T extends EC_Data> List<Map.Entry<EC_Curve, List<T>>> mapKeyToCurve(Collection<T> data, Function<T, String> getter) {
+ Map<EC_Curve, List<T>> curves = new TreeMap<>();
+ for (T item : data) {
+ EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, getter.apply(item));
+ List<T> curveKeys = curves.getOrDefault(curve, new LinkedList<>());
+ curveKeys.add(item);
+ curves.putIfAbsent(curve, curveKeys);
+ }
+ for (List<T> keyList : curves.values()) {
+ Collections.sort(keyList);
+ }
+ List<Map.Entry<EC_Curve, List<T>>> curveList = new LinkedList<>();
+ curveList.addAll(curves.entrySet());
+ Comparator<Map.Entry<EC_Curve, List<T>>> c = Comparator.comparing(Map.Entry::getKey);
+ return curveList;
+ }
+
+ public static <T extends EC_Key> List<Map.Entry<EC_Curve, List<T>>> mapKeyToCurve(Collection<T> keys) {
+ return mapKeyToCurve(keys, EC_Key::getCurve);
+ }
+
+ public static List<Map.Entry<EC_Curve, List<EC_KAResult>>> mapResultToCurve(Collection<EC_KAResult> results) {
+ return mapKeyToCurve(results, EC_KAResult::getCurve);
+ }
+
+ public static <T extends EC_Data> List<Map.Entry<String, List<T>>> mapToPrefix(Collection<T> data) {
+ Map<String, List<T>> groups = new TreeMap<>();
+ for (T item : data) {
+ String prefix = item.getId().split("/")[0];
+ List<T> group = groups.getOrDefault(prefix, new LinkedList<>());
+ group.add(item);
+ groups.putIfAbsent(prefix, group);
+ }
+ for (List<T> itemList : groups.values()) {
+ Collections.sort(itemList);
+ }
+ List<Map.Entry<String, List<T>>> result = new LinkedList<>();
+ result.addAll(groups.entrySet());
+ result.sort(Comparator.comparing(Map.Entry::getKey));
+ return result;
+ }
+
public static EC_Store getInstance() {
if (instance == null) {
instance = new EC_Store();
diff --git a/src/cz/crcs/ectester/data/bn/bn158.csv b/src/cz/crcs/ectester/data/bn/bn158.csv
new file mode 100644
index 0000000..2e3b6b7
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn158.csv
@@ -0,0 +1 @@
+0x24240D8241D5445106C8442084001384E0000013,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000011,0x24240D8241D5445106C8442084001384E0000012,0x0000000000000000000000000000000000000004,0x24240D8241D5445106C7E3F07E0010842000000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn190.csv b/src/cz/crcs/ectester/data/bn/bn190.csv
new file mode 100644
index 0000000..feb225b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn190.csv
@@ -0,0 +1 @@
+0x240001B0000948001E60004134005F10005DC0003A800013,0x000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000001001,0x240001B0000948001E60004134005F10005DC0003A800012,0x000000000000000000000000000000000000000000000040,0x240001B0000948001E600040D4005CD0005760003180000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn222.csv b/src/cz/crcs/ectester/data/bn/bn222.csv
new file mode 100644
index 0000000..89038b3
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn222.csv
@@ -0,0 +1 @@
+0x23DC0D7DC02402CDE486F4C00015B5215C0000004C6CE00000000067,0x00000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000101,0x23DC0D7DC02402CDE486F4C00015B5215C0000004C6CE00000000066,0x00000000000000000000000000000000000000000000000000000010,0x23DC0D7DC02402CDE486F4C00015555156000000496DA00000000061,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn254.csv b/src/cz/crcs/ectester/data/bn/bn254.csv
new file mode 100644
index 0000000..de71c5d
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn254.csv
@@ -0,0 +1 @@
+0x2523648240000001BA344D80000000086121000000000013A700000000000013,0x0000000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000000000000000000000000002,0x2523648240000001BA344D80000000086121000000000013A700000000000012,0x0000000000000000000000000000000000000000000000000000000000000001,0x2523648240000001BA344D8000000007FF9F800000000010A10000000000000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn286.csv b/src/cz/crcs/ectester/data/bn/bn286.csv
new file mode 100644
index 0000000..46d677e
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn286.csv
@@ -0,0 +1 @@
+0x240900D8991B25B0E2CB51DDA534A205391892080A008108000853813800138000000013,0x000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000002,0x240900D8991B25B0E2CB51DDA534A205391892080A008108000853813800138000000012,0x000000000000000000000000000000000000000000000000000000000000000000000001,0x240900D8991B25B0E2CB51DDA534A205391831FC099FC0FC0007F081080010800000000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn318.csv b/src/cz/crcs/ectester/data/bn/bn318.csv
new file mode 100644
index 0000000..bc431fe
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn318.csv
@@ -0,0 +1 @@
+0x24009000D800900024075015F015F0075000008F411E808F4000000004E484E4800000000000101B,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000002,0x24009000D800900024075015F015F0075000008F411E808F4000000004E484E4800000000000101A,0x00000000000000000000000000000000000000000000000000000000000000000000000000000001,0x24009000D800900024075015F015F0075000008EE11DC08EE000000004DB84DB8000000000000FE5,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn350.csv b/src/cz/crcs/ectester/data/bn/bn350.csv
new file mode 100644
index 0000000..237a255
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn350.csv
@@ -0,0 +1 @@
+0x23FFB80035FFEE24020A01CAFD738EC3F24B475EBC0AD0F6A0530FD78443FDF01A3FF64084000004E0000013,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000002,0x23FFB80035FFEE24020A01CAFD738EC3F24B475EBC0AD0F6A0530FD78443FDF01A3FF64084000004E0000012,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x23FFB80035FFEE24020A01CAFD738EC3F24B475EBC0A70F70052F7D78413FE08173FF7C07E0000042000000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn382.csv b/src/cz/crcs/ectester/data/bn/bn382.csv
new file mode 100644
index 0000000..955882a
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn382.csv
@@ -0,0 +1 @@
+0x240026400F3D82B2E42DE125B00158405B710818AC00000840046200950400000000001380052E000000000000000013,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002,0x240026400F3D82B2E42DE125B00158405B710818AC00000840046200950400000000001380052E000000000000000012,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x240026400F3D82B2E42DE125B00158405B710818AC000007E0042F008E3E00000000001080046200000000000000000D,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/bn/bn414.csv b/src/cz/crcs/ectester/data/bn/bn414.csv
new file mode 100644
index 0000000..0c7eb66
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn414.csv
@@ -0,0 +1 @@
+0x240024000D7EE23F2823CA035D31B144364C75E59AEFFF60544845142000765EFFF7C0000021138004DFFFFFD900000000000013,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002,0x240024000D7EE23F2823CA035D31B144364C75E59AEFFF60544845142000765EFFF7C0000021138004DFFFFFD900000000000012,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x240024000D7EE23F2823CA035D31B144364C75E59AEFFF605447E513F00070607FF82000001F9080041FFFFFDF0000000000000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn446.csv b/src/cz/crcs/ectester/data/bn/bn446.csv
new file mode 100644
index 0000000..a0a525e
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn446.csv
@@ -0,0 +1 @@
+0x2400000000000000002400000002D00000000D800000021C0000001800000000870000000B0400000057C00000015C000000132000000067,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101,0x2400000000000000002400000002D00000000D800000021C0000001800000000870000000B0400000057C00000015C000000132000000066,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,0x2400000000000000002400000002D00000000D800000021C00000017A0000000870000000AD400000054C000000156000000126000000061,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn478.csv b/src/cz/crcs/ectester/data/bn/bn478.csv
new file mode 100644
index 0000000..9c2640a
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn478.csv
@@ -0,0 +1 @@
+0x23FFFFFFFFFFFFFEDFFFFFFFEE0001B3600000006BFFF5DB835FFF5D28085442328002888F96F2944D7DED781430FFD780065FFF010020FFFD900013,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002,0x23FFFFFFFFFFFFFEDFFFFFFFEE0001B3600000006BFFF5DB835FFF5D28085442328002888F96F2944D7DED781430FFD780065FFF010020FFFD900012,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x23FFFFFFFFFFFFFEDFFFFFFFEE0001B3600000006BFFF5DB835FFF5D2807F442328002888F9872944D7E0578112F7FD780062FFF07001F7FFDF0000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn510.csv b/src/cz/crcs/ectester/data/bn/bn510.csv
new file mode 100644
index 0000000..9dc79b3
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn510.csv
@@ -0,0 +1 @@
+0x2400000000000000003F000000000001B0002958000000000237000C0F0000084000F8100151A400073800242D00001380019440000000000888000000000013,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101,0x2400000000000000003F000000000001B0002958000000000237000C0F0000084000F8100151A400073800242D00001380019440000000000888000000000012,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,0x2400000000000000003F000000000001B0002958000000000237000C0F000007E000F8100151A40006E400242D000010800181E000000000073800000000000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn542.csv b/src/cz/crcs/ectester/data/bn/bn542.csv
new file mode 100644
index 0000000..1a50175
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn542.csv
@@ -0,0 +1 @@
+0x2400090000D80009000024000090001B01B1B051090510001B00D8001B0510D8A2084511080008D000090510005110800108138025380001B00000084000001380000013,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002,0x2400090000D80009000024000090001B01B1B051090510001B00D8001B0510D8A2084511080008D000090510005110800108138025380001B00000084000001380000012,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x2400090000D80009000024000090001B01B1B051090510001B00D8001B0510D8A207E510FC0008700009051000510FC000FC108025080001B0000007E00000108000000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn574.csv b/src/cz/crcs/ectester/data/bn/bn574.csv
new file mode 100644
index 0000000..1d547c7
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn574.csv
@@ -0,0 +1 @@
+0x2400023FFFFB7FFF4C00002400167FFFEE01AEE014423FAEFFFB5C000A200050FFFF2808400041FFFE73FFF7C000210000000000001380004DFFFD90000000000000000000000013,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002,0x2400023FFFFB7FFF4C00002400167FFFEE01AEE014423FAEFFFB5C000A200050FFFF2808400041FFFE73FFF7C000210000000000001380004DFFFD90000000000000000000000012,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x2400023FFFFB7FFF4C00002400167FFFEE01AEE014423FAEFFFB5C000A200050FFFF2807E0003EFFFE85FFF820001F80000000000010800041FFFDF000000000000000000000000D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn606.csv b/src/cz/crcs/ectester/data/bn/bn606.csv
new file mode 100644
index 0000000..f488ab2
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn606.csv
@@ -0,0 +1 @@
+0x23FFFFFFFFFFFEE00000000000036000000241AFFB7FFFFFF275E0024000001B1440000D94482DF27FFFC9AEDF0000000036512100245142137FFFFFB75D7BD900000000000000246C844E13,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002,0x23FFFFFFFFFFFEE00000000000036000000241AFFB7FFFFFF275E0024000001B1440000D94482DF27FFFC9AEDF0000000036512100245142137FFFFFB75D7BD900000000000000246C844E12,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x23FFFFFFFFFFFEE00000000000036000000241AFFB7FFFFFF275E0024000001B1440000D9447CDF27FFFC9AEE08000000036511F8024513F107FFFFFB75D81DF00000000000000246C7E420D,0x01
diff --git a/src/cz/crcs/ectester/data/bn/bn638.csv b/src/cz/crcs/ectester/data/bn/bn638.csv
new file mode 100644
index 0000000..cb54f9b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/bn638.csv
@@ -0,0 +1 @@
+0x23FFFFFDC000000D7FFFFFB8000001D3FFFFF942D000165E3FFF94870000D52FFFFDD0E00008DE55C00086520021E55BFFFFF51FFFF4EB800000004C80015ACDFFFFFFFFFFFFECE00000000000000067,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101,0x23FFFFFDC000000D7FFFFFB8000001D3FFFFF942D000165E3FFF94870000D52FFFFDD0E00008DE55C00086520021E55BFFFFF51FFFF4EB800000004C80015ACDFFFFFFFFFFFFECE00000000000000066,0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010,0x23FFFFFDC000000D7FFFFFB8000001D3FFFFF942D000165E3FFF94870000D52FFFFDD0E00008DE55600086550021E555FFFFF54FFFF4EAC000000049800154D9FFFFFFFFFFFFEDA00000000000000061,0x01
diff --git a/src/cz/crcs/ectester/data/bn/curves.xml b/src/cz/crcs/ectester/data/bn/curves.xml
new file mode 100644
index 0000000..ddf2263
--- /dev/null
+++ b/src/cz/crcs/ectester/data/bn/curves.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<curves xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../schema.xsd">
+ <curve>
+ <id>bn158</id>
+ <bits>158</bits>
+ <field>prime</field>
+ <file>bn158.csv</file>
+ </curve>
+ <curve>
+ <id>bn190</id>
+ <bits>190</bits>
+ <field>prime</field>
+ <file>bn190.csv</file>
+ </curve>
+ <curve>
+ <id>bn222</id>
+ <bits>222</bits>
+ <field>prime</field>
+ <file>bn222.csv</file>
+ </curve>
+ <curve>
+ <id>bn254</id>
+ <bits>254</bits>
+ <field>prime</field>
+ <file>bn254.csv</file>
+ </curve>
+ <curve>
+ <id>bn286</id>
+ <bits>286</bits>
+ <field>prime</field>
+ <file>bn286.csv</file>
+ </curve>
+ <curve>
+ <id>bn318</id>
+ <bits>318</bits>
+ <field>prime</field>
+ <file>bn318.csv</file>
+ </curve>
+ <curve>
+ <id>bn350</id>
+ <bits>350</bits>
+ <field>prime</field>
+ <file>bn350.csv</file>
+ </curve>
+ <curve>
+ <id>bn382</id>
+ <bits>382</bits>
+ <field>prime</field>
+ <file>bn382.csv</file>
+ </curve>
+ <curve>
+ <id>bn414</id>
+ <bits>414</bits>
+ <field>prime</field>
+ <file>bn414.csv</file>
+ </curve>
+ <curve>
+ <id>bn446</id>
+ <bits>446</bits>
+ <field>prime</field>
+ <file>bn446.csv</file>
+ </curve>
+ <curve>
+ <id>bn478</id>
+ <bits>478</bits>
+ <field>prime</field>
+ <file>bn478.csv</file>
+ </curve>
+ <curve>
+ <id>bn510</id>
+ <bits>510</bits>
+ <field>prime</field>
+ <file>bn510.csv</file>
+ </curve>
+ <curve>
+ <id>bn542</id>
+ <bits>542</bits>
+ <field>prime</field>
+ <file>bn542.csv</file>
+ </curve>
+ <curve>
+ <id>bn574</id>
+ <bits>574</bits>
+ <field>prime</field>
+ <file>bn574.csv</file>
+ </curve>
+ <curve>
+ <id>bn606</id>
+ <bits>606</bits>
+ <field>prime</field>
+ <file>bn606.csv</file>
+ </curve>
+ <curve>
+ <id>bn638</id>
+ <bits>638</bits>
+ <field>prime</field>
+ <file>bn638.csv</file>
+ </curve>
+</curves> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/categories.xml b/src/cz/crcs/ectester/data/categories.xml
index f123b6a..38ce683 100644
--- a/src/cz/crcs/ectester/data/categories.xml
+++ b/src/cz/crcs/ectester/data/categories.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<categories xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="schema.xsd">
+ <!-- Standard curves -->
<category>
<name>anomalous</name>
<directory>anomalous</directory>
@@ -32,24 +33,51 @@
<desc>GOST R 34.10-2001: RFC5832</desc>
</category>
<category>
- <name>composite</name>
- <directory>composite</directory>
- <desc>Composite order curves, with points of very small order pregenerated.</desc>
+ <name>x962</name>
+ <directory>x962</directory>
+ <desc>ANSI X9.62 example curves.</desc>
</category>
<category>
- <name>wrong</name>
- <directory>wrong</directory>
- <desc>Wrong field curves. These should definitely give an error when used. Since the "prime" used for the field are not prime, and the field polynomials are also not irreducible. Simply put these parameters don't specify a valid elliptic curve.</desc>
+ <name>Barreto-Naehrig</name>
+ <directory>bn</directory>
+ <desc>Barreto-Naehrig curves from: A Family of Implementation-Friendly BN Elliptic Curves - https://eprint.iacr.org/2010/429.pdf.</desc>
</category>
<category>
+ <name>other</name>
+ <directory>other</directory>
+ <desc>An assortment of some other curves.</desc>
+ </category>
+
+ <!-- Custom curves -->
+ <category>
<name>invalid</name>
<directory>invalid</directory>
- <desc></desc>
+ <desc>Invalid curves and points on them for common standard named curves.</desc>
</category>
<category>
<name>twist</name>
<directory>twist</directory>
- <desc></desc>
+ <desc>Points on quadratic twists of common standard named curves.</desc>
+ </category>
+ <category>
+ <name>degenerate</name>
+ <directory>degenerate</directory>
+ <desc>Points on degenerate curves for common standard named curves.</desc>
+ </category>
+ <category>
+ <name>cofactor</name>
+ <directory>cofactor</directory>
+ <desc>Curves of order n * p, with p prime and n in {2,4,8,16,32,64,128}. Generator of order p, with points on the subgroup of order n.</desc>
+ </category>
+ <category>
+ <name>composite</name>
+ <directory>composite</directory>
+ <desc>Composite order curves, with points of very small order pre-generated. Also curves with order of a product of two large primes.</desc>
+ </category>
+ <category>
+ <name>wrong</name>
+ <directory>wrong</directory>
+ <desc>Wrong field curves. These should definitely give an error when used. Since the "prime" used for the field is not prime, and the field polynomials are also not irreducible. Simply put these parameters don't specify a valid elliptic curve.</desc>
</category>
<category>
<name>test</name>
@@ -57,8 +85,13 @@
<desc>Test vectors</desc>
</category>
<category>
- <name>x962</name>
- <directory>x962</directory>
- <desc>ANSI X9.62 example curves.</desc>
+ <name>wycheproof</name>
+ <directory>wycheproof</directory>
+ <desc>Test cases from google Wycheproof project: https://github.com/google/wycheproof</desc>
+ </category>
+ <category>
+ <name>supersingular</name>
+ <directory>supersingular</directory>
+ <desc>Some supersingular curves, over F_p with order equal to p + 1.</desc>
</category>
</categories> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor128p128.csv b/src/cz/crcs/ectester/data/cofactor/cofactor128p128.csv
new file mode 100644
index 0000000..58459f6
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor128p128.csv
@@ -0,0 +1 @@
+0xb0b4005fd28fe7fb494b680e5ad7e1f5,0x6409a6ac9e446c1fa2c1432cbbd17c23,0x646e70d0490d799b8664d791cf34c9a8,0x1b3bdc3ea1be0329a69f6bb398437628,0x2fb05dc71eba40937f233c8d5d672ebb,0x1616800bfa51fcff7618e79d118d6b1,0x80 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor128p16.csv b/src/cz/crcs/ectester/data/cofactor/cofactor128p16.csv
new file mode 100644
index 0000000..181c47c
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor128p16.csv
@@ -0,0 +1 @@
+0xf723fda094465e1328ca65dfe04ae01b,0x5c1145c56795ae08d3f96d7451db5389,0x3eafb22339feab41ab6069ec1188ea7d,0x6ec8bbabff3e264c59d152c03a29fb26,0x8c8e8e721c8817528cd243667d023095,0xf723fda094465e13cb5a5cc981c945f,0x10 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor128p2.csv b/src/cz/crcs/ectester/data/cofactor/cofactor128p2.csv
new file mode 100644
index 0000000..d9857d8
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor128p2.csv
@@ -0,0 +1 @@
+0xf07c2775c51f358b8bdab54821aaa5ab,0x54e4afb6f93de32081be13f858262bc7,0xe13c739a7fe7f62812babb3cba8c6b1f,0x43cefc1ddc7d6936b0db49ecb4b8c4d9,0x52579151eb2779295b75cd7226895abb,0x783e13bae28f9ac60c18591fe953fbf7,0x2 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor128p32.csv b/src/cz/crcs/ectester/data/cofactor/cofactor128p32.csv
new file mode 100644
index 0000000..9673835
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor128p32.csv
@@ -0,0 +1 @@
+0x8d4ee802a67d0de73b9ec4f1a70227b7,0x70b4c15289f93fbc9247509fc9085396,0x04dfb7818caa18da2a60b50f0056a62b,0x09907655c9579e02b30534529dc0031a,0x365f28ab09d64508b47519fea58f4035,0x46a77401533e86f405231d0d851b3d9,0x20 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor128p4.csv b/src/cz/crcs/ectester/data/cofactor/cofactor128p4.csv
new file mode 100644
index 0000000..44363ad
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor128p4.csv
@@ -0,0 +1 @@
+0x94d9020b666fbb599609485472a9246f,0x8220ebe30c27e10f945b0c2cdfe6dcaa,0x1914928b1a349161061165128629ea88,0x6a1a526fe3d4f719082872b2d149a90f,0x423351dae6533a1a916b151cd0783165,0x25364082d99beed620f8082db41374e7,0x4 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor128p64.csv b/src/cz/crcs/ectester/data/cofactor/cofactor128p64.csv
new file mode 100644
index 0000000..35a5ecc
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor128p64.csv
@@ -0,0 +1 @@
+0xc3d6db041a0c509309d706a52a9ae20d,0x6234008af9a67b1a0cf123a38a46d0fb,0x65ca327cc79249fd9b4f3a1c15890787,0x57c0a37da59815687f752f724f015b21,0x9136e347e107c2f5face9abd739f6a82,0x30f5b6c1068314251fbe0d341f0c569,0x40 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor128p8.csv b/src/cz/crcs/ectester/data/cofactor/cofactor128p8.csv
new file mode 100644
index 0000000..94d4b4e
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor128p8.csv
@@ -0,0 +1 @@
+0xe65f3e99554260c832ee6c21ec3ac437,0x0ff5c77f9c00ad42c58878e9510a059e,0x0652b998c3bfeefe20afc97a2b6595f4,0xc8a6fef9cbda700c097a1c3ddcaf3d0d,0x602bc0de98577bf266432e60fabe4946,0x1ccbe7d32aa84c191817ef7e51812989,0x8 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor160p16.csv b/src/cz/crcs/ectester/data/cofactor/cofactor160p16.csv
new file mode 100644
index 0000000..4d82274
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor160p16.csv
@@ -0,0 +1 @@
+0x85836f09b17d1ec0cdeda21b55485e18dd968323,0x5480f9557c649a8e30f1e1256d07b0e32483ac68,0x0ecd880812f41c97be8b5daf1865725753b2ba37,0x16e1dd32469e75aa72a1dc48b78587b18e4f9874,0x70920054032065a09fad53a3ca69de634634a421,0x85836f09b17d1ec0cdecfe96b46937bbf135dab,0x10 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor160p2.csv b/src/cz/crcs/ectester/data/cofactor/cofactor160p2.csv
new file mode 100644
index 0000000..54717af
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor160p2.csv
@@ -0,0 +1 @@
+0xd3622579d76435736f05756763249bb0facdc4a3,0xa645cc4161eb7cd8839b6e26c3efb6734b5bdc65,0xb1900e655c426daea7b80fecdd77ba19a9bb473c,0x2cfbf234e0d99ce44fdaedd2ec2e01558e6d7fd7,0x1495986fef15ada29c39866ac03ddc934589dffc,0x69b112bcebb21ab9b782a0dac36ea8fa7be5fd1b,0x2 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor160p32.csv b/src/cz/crcs/ectester/data/cofactor/cofactor160p32.csv
new file mode 100644
index 0000000..75238ea
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor160p32.csv
@@ -0,0 +1 @@
+0x91634da0ec681dd6ba65beaf596d82b262b4cded,0x747c9302638253325e847cb5f0cf71134e672ec5,0x68ac504eba7a475a52b2bff92b5b77fb16f124b8,0x721dbbff58bc41dff64da7bd7a45d9892f659306,0x6d353cfdf9570402ccd11b9651a2d4be5d4f1853,0x48b1a6d076340eeb5d33371825941b3e0012e99,0x20 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor160p4.csv b/src/cz/crcs/ectester/data/cofactor/cofactor160p4.csv
new file mode 100644
index 0000000..760dbef
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor160p4.csv
@@ -0,0 +1 @@
+0x93ab454ad26dae3b521d5b61a48c94cab3c4aa9d,0x4b2d384edb6b10bdaf4c608cc5aff078c4c58e38,0x35bc442cc9f7fe4317cf36d4f411c98f26956527,0x216d191d642aab59fca4ec18b95e11a298da5a00,0x09d9b5f44253719aeb44d3986c40ee3d9c9d86c9,0x24ead152b49b6b8ed4874ccca8f78da90add8ceb,0x4 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor160p64.csv b/src/cz/crcs/ectester/data/cofactor/cofactor160p64.csv
new file mode 100644
index 0000000..4cdcfdc
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor160p64.csv
@@ -0,0 +1 @@
+0xfe2a2fe87bef6a429245c029cf205f06e16cd249,0xc42dc19e1c0c0b0dd27758d2787d526b25ad89b5,0xf72edb299fab1b613708d4165ededab65350fe6c,0x104a825944921b469704babb2727e5f8a829f2e1,0x8b955a5059e68cc0e932bbdb90fe81730c8e4d19,0x3f8a8bfa1efbda90a4917c6c340f970a5fce9c3,0x40 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor160p8.csv b/src/cz/crcs/ectester/data/cofactor/cofactor160p8.csv
new file mode 100644
index 0000000..60ca98e
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor160p8.csv
@@ -0,0 +1 @@
+0xe40476bfeb2a3fd21ad80c102aad29f61cec5eaf,0x544ccbf7202e6b6d27fc19a3587eecc4ec665430,0x86690f7849e1707b28c24b718e7ffa36b55677b5,0x836cee7bcecb29d171c4bd9a1b4943e8159e4708,0xa0add6ab4a0729fd2719e5767abfc4d4c49ff802,0x1c808ed7fd6547fa435b03ffd3b931cccc8c098f,0x8 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor163t128.csv b/src/cz/crcs/ectester/data/cofactor/cofactor163t128.csv
new file mode 100644
index 0000000..c748587
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor163t128.csv
@@ -0,0 +1 @@
+0xa3,0x8,0x2,0x1,0x02391521a0d15b5eee4cae4cb3628d79479cb15700,0x004095708f687ea59f768ee27e167117b9401c223e,0x01925be8ca3bbee060bd2041c5fe0652be1f2d8942,0x024e103317a95c4d6c5b731c67d87688dd15a3cf7d,0x1000000000000000000001b01bb79598eedfebcf,0x80
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor163t16.csv b/src/cz/crcs/ectester/data/cofactor/cofactor163t16.csv
new file mode 100644
index 0000000..decdad3
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor163t16.csv
@@ -0,0 +1 @@
+0xa3,0x8,0x2,0x1,0x0574f63f2c0fc757663ccda72b2ec8a37e7c84dfbc,0x03816a247d9618c4d1431793a2b9aaa8c5235ba047,0x074e2cfe3199fe1d5fb2cd8cc2e9aa8bf82ec4e90a,0x02942efd0f0619aaabd77de3f48da81138ab6dccc6,0x7fffffffffffffffffffbd3a47e6e6c2e2d09335,0x10
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor163t2.csv b/src/cz/crcs/ectester/data/cofactor/cofactor163t2.csv
new file mode 100644
index 0000000..d837a28
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor163t2.csv
@@ -0,0 +1 @@
+0xa3,0x8,0x2,0x1,0x020e850e21d5bfce24ff184c220ea69b20bad05c65,0x0547b079a38b6094672f6cb5adefa94ba1a29d977b,0x0156bee74ac2552ee999cff24e1d7c471ffc17d0c7,0x04a955c7e3b3534d9fd168d9fbffea3acca23c1fdd,0x400000000000000000001e699c7714c35b242f43b,0x2 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor163t32.csv b/src/cz/crcs/ectester/data/cofactor/cofactor163t32.csv
new file mode 100644
index 0000000..2b88982
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor163t32.csv
@@ -0,0 +1 @@
+0xa3,0x8,0x2,0x1,0x04a4e7bb96ff9007b4be8097c5c4e36701e3f22aa8,0x020d55ea20c74a09f86cc1b2ecf2d073f46ad9b7fa,0x05f7347502518870fc7419e2d0e3170d5b04333a48,0x05951c6d70c789d60bd25b2519416dc756da26d320,0x3fffffffffffffffffffe88d1f6ec2029eaf4f9d,0x20
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor163t4.csv b/src/cz/crcs/ectester/data/cofactor/cofactor163t4.csv
new file mode 100644
index 0000000..61f7b03
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor163t4.csv
@@ -0,0 +1 @@
+0xa3,0x8,0x2,0x1,0x027b506a68264c13994a74473ebd0506ce33921b00,0x0483681d34fdc0544a690cd8363ef6876bc9df5b09,0x051d0095b0d49e8b9b2e38a49ab58abb28b8301349,0x0427559b4db514f0659cbc45a1a785ff3c32f0d0c5,0x1fffffffffffffffffffff89941a8461c966379ad,0x4 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor163t64.csv b/src/cz/crcs/ectester/data/cofactor/cofactor163t64.csv
new file mode 100644
index 0000000..6d3ee91
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor163t64.csv
@@ -0,0 +1 @@
+0xa3,0x8,0x2,0x1,0x041a27de41f0e09c7cd4ff65fe10d472c9ca652ea1,0x00b27568b80c64d610ffdde6b3f520df0e0c499aa8,0x04f3cce508325c822a5e04044014d785e9b55ef95e,0x010021cb58589ea7cc7a8caea926276eb32db24b45,0x1ffffffffffffffffffff192d95b4d882a5ee3b9,0x40
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor163t8.csv b/src/cz/crcs/ectester/data/cofactor/cofactor163t8.csv
new file mode 100644
index 0000000..349e874
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor163t8.csv
@@ -0,0 +1 @@
+0xa3,0x8,0x2,0x1,0x0183b7c0268ef09222560b602c9444aeb218a9b1c8,0x0035948fa062ffab3e7e63de769fec1407c6b85c6c,0x04d3aaef5f5075d1bbf92e9a5393af45b6946e2074,0x041df30932c95f4732fd59593e11aef8bb46ef3b6c,0x100000000000000000000762c81022ff40e2843f1,0x8 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor233t128.csv b/src/cz/crcs/ectester/data/cofactor/cofactor233t128.csv
new file mode 100644
index 0000000..48505d4
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor233t128.csv
@@ -0,0 +1 @@
+0xe9,0x4a,0x0,0x0,0x010ce87b92d6866c18d14efba7025388574f670476169b09929bbe2b7a4a,0x001ab1f0aecfe5ee45923aad73ea5fa24b554f91ff41a8fd5529d55e76f8,0x009d7d0edc1868aa15931051f8b084e25e8b0f2098994483cab3737c021e,0x01f663c194c41dd386976d105acd3be135ceb5f0d69f932565bc4706e2a9,0x3ffffffffffffffffffffffffffffd7489d946218417d25b50e07c781,0x80 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor233t16.csv b/src/cz/crcs/ectester/data/cofactor/cofactor233t16.csv
new file mode 100644
index 0000000..d838407
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor233t16.csv
@@ -0,0 +1 @@
+0xe9,0x4a,0x0,0x0,0x017e449f630dcabb0206c5d3d788c030f5b817f7a9b37e9a851aa511e3b9,0x0134978d6868f9c83bfee60f609e31efa87910ccbe160ef2096fe06dc179,0x00bbcfcfdfb70ec830fb88d68d78dbbceaacd5d072194bf584e5e13c82a7,0x0177b6ab31a325d0e23664224bef711cdf9c2abb9f4016777519ead3c1be,0x1ffffffffffffffffffffffffffffec2ff067f4db9e97b04f2f6e5cac3,0x10 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor233t2.csv b/src/cz/crcs/ectester/data/cofactor/cofactor233t2.csv
new file mode 100644
index 0000000..61a945f
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor233t2.csv
@@ -0,0 +1 @@
+0xe9,0x4a,0x0,0x0,0x019a6dad09843e156188ee96105aa483897804180dc3f47e9ffed7b51d76,0x00bc002063484a714b1ca2a677fe17fb6c27843689568889c6d3088efce0,0x0117230ce450dd966713f13cfab77972da6680aaad37bc6409b4d153b36a,0x0071b5d13375216cf1e0ddc0bd2b243bad4a91f55c724b7d68af2db21602,0xfffffffffffffffffffffffffffff7359ae340ea86da4edade0cf53e23,0x2 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor233t32.csv b/src/cz/crcs/ectester/data/cofactor/cofactor233t32.csv
new file mode 100644
index 0000000..4f14dfe
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor233t32.csv
@@ -0,0 +1 @@
+0xe9,0x4a,0x0,0x0,0x013c676464927c22282b42616b5d5e09a85468727495eae00e57afd170b8,0x009c6a29ca055f2c9b6714f529a83151c68f44bdbdf86d2f87a40cd8d8ec,0x01d12094657da0b94c14ab67b1ce85c4b16042e29b65ace2e448f4b3b8fd,0x012862bf9015dc35bf721429723ebf870cd026aff3acdc4282d0ff8f847f,0xfffffffffffffffffffffffffffffe6f9adb7f42e7c7ed65369ce8495,0x20 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor233t4.csv b/src/cz/crcs/ectester/data/cofactor/cofactor233t4.csv
new file mode 100644
index 0000000..1972de2
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor233t4.csv
@@ -0,0 +1 @@
+0xe9,0x4a,0x0,0x0,0x01d16ca19fdddd29cbef9f7d8edcd5bd5a2e51b1331f456d9a7c07ee40ef,0x00b59ca10c75cab015f7932ea7791a90d0edecba979a8ddaeca053d802b8,0x0163e7db23aacfce4573c1c72a8e09d064a5b99e3975ddbeb38ea66dd115,0x012a42b5d1b9614640705e86637fd3d5df1e988d843feab2df701ed0d2b3,0x8000000000000000000000000000061aa6c6684ad065bd4087bc36316d,0x4 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor233t64.csv b/src/cz/crcs/ectester/data/cofactor/cofactor233t64.csv
new file mode 100644
index 0000000..df9e357
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor233t64.csv
@@ -0,0 +1 @@
+0xe9,0x4a,0x0,0x0,0x003037f3c3b8be56c1b40f21898a14c0506810a2c2edee866d98d155bafe,0x010c0d410fef2163d820cf726df422e57f28ecb380587a8a166217b49fbf,0x01d00a40f4a7da1dfc8f87b8fc9981beebec0a5336452a7732c3216a5d71,0x0077dc35e9d9a730d80a7f5e22e8df145ea82ee8bd7bc178a9d14f3d6e4f,0x7fffffffffffffffffffffffffffff58ae3a5ab58e4794d5a0d31a0df,0x40 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/cofactor233t8.csv b/src/cz/crcs/ectester/data/cofactor/cofactor233t8.csv
new file mode 100644
index 0000000..43f6705
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/cofactor233t8.csv
@@ -0,0 +1 @@
+0xe9,0x4a,0x0,0x0,0x01c2ddc23a454bacf481ab17cd223d5b9b452c50de07c65c4eb3bb2a6c2f,0x01db7ca30cf0915e8ee53c3ba32371bc73a73f4f499839257a861f6123f8,0x0101da5b2520f16fba2d08f3687db69862ecfec9aa3cd81e3a53120c596c,0x0095d00741d7dc2119cb427b8a0dd77a2bcaef233086dd7704a438e0294e,0x3ffffffffffffffffffffffffffffc34eca9e37b884d13683d26dc874f,0x8 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/cofactor/curves.xml b/src/cz/crcs/ectester/data/cofactor/curves.xml
new file mode 100644
index 0000000..bb8a905
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/curves.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<curves xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../schema.xsd">
+
+ <curve>
+ <id>cofactor128p2</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>cofactor128p2.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor128p4</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>cofactor128p4.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor128p8</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>cofactor128p8.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor128p16</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>cofactor128p16.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor128p32</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>cofactor128p32.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor128p64</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>cofactor128p64.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor128p128</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>cofactor128p128.csv</file>
+ </curve>
+
+ <curve>
+ <id>cofactor160p2</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>cofactor160p2.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor160p4</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>cofactor160p4.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor160p8</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>cofactor160p8.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor160p16</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>cofactor160p16.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor160p32</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>cofactor160p32.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor160p64</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>cofactor160p64.csv</file>
+ </curve>
+
+
+ <curve>
+ <id>cofactor163t2</id>
+ <bits>163</bits>
+ <field>binary</field>
+ <file>cofactor163t2.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor163t4</id>
+ <bits>163</bits>
+ <field>binary</field>
+ <file>cofactor163t4.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor163t8</id>
+ <bits>163</bits>
+ <field>binary</field>
+ <file>cofactor163t8.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor163t16</id>
+ <bits>163</bits>
+ <field>binary</field>
+ <file>cofactor163t16.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor163t32</id>
+ <bits>163</bits>
+ <field>binary</field>
+ <file>cofactor163t32.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor163t64</id>
+ <bits>163</bits>
+ <field>binary</field>
+ <file>cofactor163t64.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor163t128</id>
+ <bits>163</bits>
+ <field>binary</field>
+ <file>cofactor163t128.csv</file>
+ </curve>
+
+ <curve>
+ <id>cofactor233t2</id>
+ <bits>233</bits>
+ <field>binary</field>
+ <file>cofactor233t2.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor233t4</id>
+ <bits>233</bits>
+ <field>binary</field>
+ <file>cofactor233t4.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor233t8</id>
+ <bits>233</bits>
+ <field>binary</field>
+ <file>cofactor233t8.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor233t16</id>
+ <bits>233</bits>
+ <field>binary</field>
+ <file>cofactor233t16.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor233t32</id>
+ <bits>233</bits>
+ <field>binary</field>
+ <file>cofactor233t32.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor233t64</id>
+ <bits>233</bits>
+ <field>binary</field>
+ <file>cofactor233t64.csv</file>
+ </curve>
+ <curve>
+ <id>cofactor233t128</id>
+ <bits>233</bits>
+ <field>binary</field>
+ <file>cofactor233t128.csv</file>
+ </curve>
+</curves>
diff --git a/src/cz/crcs/ectester/data/cofactor/keys.xml b/src/cz/crcs/ectester/data/cofactor/keys.xml
new file mode 100644
index 0000000..8cf19a1
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/keys.xml
@@ -0,0 +1,707 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE keys [
+ <!ENTITY secg SYSTEM "cofactor/secg_keys.xml">
+ ]>
+<keys xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../schema.xsd"
+ category="cofactor"
+ desc="">
+
+ <pubkey>
+ <id>cofactor128p2/0</id>
+ <inline>0x1274cf343b12c9de044a312c7e0d88b1,0x00000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor128p2</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p4/0</id>
+ <inline>0x4e5a1eb60f6d2cb5c24f6ea54a675cd6,0x00000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor128p4</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p4/1</id>
+ <inline>0x71223b82022305c5eb81f5c3ae3f785a,0x79fc820c0eecef0bca540a3e723583ff</inline>
+ <curve>cofactor/cofactor128p4</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p8/0</id>
+ <inline>0x31eb5f732057b0ea57eed55f4259d85d,0x00000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor128p8</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p8/1</id>
+ <inline>0x2e7bb6ad57bbcbef6dc2bf4245a38c12,0x61d860ec5fe722872c35dfa1ef84a307</inline>
+ <curve>cofactor/cofactor128p8</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p8/2</id>
+ <inline>0x901934de82c48d1058c67c605a9a390b,0x335c2e8e79a171506a99490d3332a110</inline>
+ <curve>cofactor/cofactor128p8</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p16/0</id>
+ <inline>0x89578c4527e2d5e8a95905e30f0889e3,0x00000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor128p16</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p16/1</id>
+ <inline>0x99efc5bd2e9adc1c00919ddf5bf7ace0,0x082767ef35dad2259725c77e68bf8a69</inline>
+ <curve>cofactor/cofactor128p16</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p16/2</id>
+ <inline>0x5e2f995dad72a38bd8c9f9a7f465ce6f,0xc6dc35c4d28a668f8240ef6ac2536b14</inline>
+ <curve>cofactor/cofactor128p16</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p16/3</id>
+ <inline>0xe719245896fb0737d55085e208aafec2,0xf672a92221d12ed6ec4657ca767a7f06</inline>
+ <curve>cofactor/cofactor128p16</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p32/0</id>
+ <inline>0x097191ee5ded1c36f2ec6bba78e7e6ea,0x00000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor128p32</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p32/1</id>
+ <inline>0x527a9d644ebae128748327d1961c3985,0x4edca8a611b16dee95eeea363724062d</inline>
+ <curve>cofactor/cofactor128p32</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p32/2</id>
+ <inline>0x5faf8263ac8c51084b0aff1bd428f092,0x2680273ff79343d47280c69168973cf5</inline>
+ <curve>cofactor/cofactor128p32</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p32/3</id>
+ <inline>0x0351f0e0b0de971c953918934f59c8c0,0x424957e4a6756cc1e55d36489cff3d8b</inline>
+ <curve>cofactor/cofactor128p32</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p32/4</id>
+ <inline>0x5c5e4942cf366e1b04bed7b1ca3bd4a9,0x3549e46c6696ed157ccc74adc65683ae</inline>
+ <curve>cofactor/cofactor128p32</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p64/0</id>
+ <inline>0x1d360b7f2f805be59aedeaae2813ee1f,0x00000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor128p64</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p64/1</id>
+ <inline>0x87c97b7182f883ded6560cd78264ad5b,0x468dbd5fe82135ea24a71059341f16cb</inline>
+ <curve>cofactor/cofactor128p64</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p64/2</id>
+ <inline>0x9498a4ec5caf6d7d8638dc6d79ae30d7,0x4a8412b51a48b34c6f33047052979ebf</inline>
+ <curve>cofactor/cofactor128p64</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p64/3</id>
+ <inline>0x7bd10415384645d1dfe4c84e8f05c301,0x37878a8d0088d16cf88f49c07c13147b</inline>
+ <curve>cofactor/cofactor128p64</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p64/4</id>
+ <inline>0x9781df3d77ae756e8cb031303f7332a1,0xb0014e02d54b017e4069401fc41a9a23</inline>
+ <curve>cofactor/cofactor128p64</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p64/5</id>
+ <inline>0xb8fde1c676a1ceab9ad6597f9763c79f,0x5490d7c81d8ddece1a4081a743910b46</inline>
+ <curve>cofactor/cofactor128p64</curve>
+ <desc>cofactor order = 64</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p128/0</id>
+ <inline>0x485b34188824c54f115f31891c18795c,0x00000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor128p128</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p128/1</id>
+ <inline>0x1e75df97d9c90de9338ea741cc6fa72e,0x80308fe46db0ed0486bb204c97cb0891</inline>
+ <curve>cofactor/cofactor128p128</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p128/2</id>
+ <inline>0x789c0de0acc72fa82609c27b1ff26031,0x38eaf5e148dd91fe151cc072ce4945be</inline>
+ <curve>cofactor/cofactor128p128</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p128/3</id>
+ <inline>0xace50433b400257c911cbcc175bf03a1,0x6f0cd218b21a252a289d49981a554232</inline>
+ <curve>cofactor/cofactor128p128</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p128/4</id>
+ <inline>0x0144308e82b8c4edd3b02a535fcd9b11,0x241c16e9c41948dd249741b623ae6f46</inline>
+ <curve>cofactor/cofactor128p128</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p128/5</id>
+ <inline>0x17c76910a9acbde84033e2fcc629350a,0x462e9fa1f47d82b3e82c813368ffe005</inline>
+ <curve>cofactor/cofactor128p128</curve>
+ <desc>cofactor order = 64</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor128p128/6</id>
+ <inline>0x2f633a2a7176d5e89e53db656761884d,0x04806528aae79ad5953f985f703fe3ed</inline>
+ <curve>cofactor/cofactor128p128</curve>
+ <desc>cofactor order = 128</desc>
+ </pubkey>
+
+ <pubkey>
+ <id>cofactor160p2/0</id>
+ <inline>0x5fa441bf614740860b6eb17c525fadf7fda8a8dd,0x0000000000000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor160p2</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p4/0</id>
+ <inline>0x023deee1d84150a62b98aa5bfc199af554653515,0x0000000000000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor160p4</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p4/1</id>
+ <inline>0x029177e40c5fa71b99189487dd216c20878ddc2b,0x8208f20780b73baa1c19aec658707b070b675de2</inline>
+ <curve>cofactor/cofactor160p4</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p8/0</id>
+ <inline>0x05e55a12fb3fc534266721e50921b87175ba6058,0x0000000000000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor160p8</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p8/1</id>
+ <inline>0xcabc8915d9a3ec3918425a100c46455dac4a69b9,0x899e34cfb8138627bddf44123ec5875bbe77607a</inline>
+ <curve>cofactor/cofactor160p8</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p8/2</id>
+ <inline>0xabe45c362bd99dc1d473ece28afe13c21fa4d759,0x7fcb17eb63260522d911eca08a4f6174163e2869</inline>
+ <curve>cofactor/cofactor160p8</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p16/0</id>
+ <inline>0x1e20529f2293f0a08cc722d7fa8e56ddd4eb3b8a,0x0000000000000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor160p16</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p16/1</id>
+ <inline>0x8076835b64ee29e80caacb94a09fbf465bb283d2,0x0a772fb6cdfc5ca2a6ce58ce77c36c3e572319f2</inline>
+ <curve>cofactor/cofactor160p16</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p16/2</id>
+ <inline>0x438873cc4cfe75ea5e4cd253a999bd383679643e,0x5aeea5de1639443278f0ef03d196cb87b9818886</inline>
+ <curve>cofactor/cofactor160p16</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p16/3</id>
+ <inline>0x76f900fcc2c879c8c78e3a2c25ff0322d3dc1234,0x0a1980eaf1f4d35f736087a4b7df844c61665c03</inline>
+ <curve>cofactor/cofactor160p16</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p32/0</id>
+ <inline>0x8cff23fa9830f93cb2d46aa5f91e6f53080fa5b7,0x0000000000000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor160p32</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p32/1</id>
+ <inline>0x776031adf083c2373e49d38f6e4fff890a723b20,0x7fb4468b1937d569889b9aa06e0e4ec66032a07f</inline>
+ <curve>cofactor/cofactor160p32</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p32/2</id>
+ <inline>0x80808ea2da912ddd3ef23c2b4a7a5f7a0c49d97f,0x0c4664470b36a7873650c0ce856eccf5c715202e</inline>
+ <curve>cofactor/cofactor160p32</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p32/3</id>
+ <inline>0x6489b721683b235b1e195df3fc588b8469a53f92,0x745764261684c3056725df16a14ae71a9ce669f8</inline>
+ <curve>cofactor/cofactor160p32</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p32/4</id>
+ <inline>0x755a0b8b58e0d8f18998e2c2b7b9ab09792323d6,0x90e7c831aba6c27762bef58bf07b782334da565d</inline>
+ <curve>cofactor/cofactor160p32</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p64/0</id>
+ <inline>0x46b72d87edddeea2fa3ef32725fcf8c1e19bf40d,0x0000000000000000000000000000000000000000</inline>
+ <curve>cofactor/cofactor160p64</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p64/1</id>
+ <inline>0x3e92edd49a08c7dc03badf986f0902292f15856d,0x7658a601d3aceb0b3273011d1211b8df18027f78</inline>
+ <curve>cofactor/cofactor160p64</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p64/2</id>
+ <inline>0xa863b1077481ae1da7e782b56ef378aa79d94da0,0xf7b8ccdfee7605bf1b858f427480a15cb2b82728</inline>
+ <curve>cofactor/cofactor160p64</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p64/3</id>
+ <inline>0x45a971943d80ce3f1f29ac86536c0e189ae98dc7,0x6e4488a53ee6cbea7ecec826a8f89f9334e90c7a</inline>
+ <curve>cofactor/cofactor160p64</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p64/4</id>
+ <inline>0x53499915b1a061db0216f7c871780abfb86c576e,0x44c57b310461b57c2d20c12dbeb64475e122e1a4</inline>
+ <curve>cofactor/cofactor160p64</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor160p64/5</id>
+ <inline>0x3fabbf2a3612a89fb5940661b4acc7589cc7fce3,0xb5489c892a82a2f4e5bced433a3c4685b9ae0d07</inline>
+ <curve>cofactor/cofactor160p64</curve>
+ <desc>cofactor order = 64</desc>
+ </pubkey>
+
+
+ <pubkey>
+ <id>cofactor163t2/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x0132720c6aa3f2ca65d18f2de81e5e6b8ad4a3ef9d</inline>
+ <curve>cofactor/cofactor163t2</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t4/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x00b93d46bc80b487e7738644e85bb6d29c2dca2600</inline>
+ <curve>cofactor/cofactor163t4</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t4/1</id>
+ <inline>0x003de55d59f7c71d1560c04954a897294b584c8840,0x069a5e172cea516563b7289330fcadd1b3a9a08ea5</inline>
+ <curve>cofactor/cofactor163t4</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t8/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x0569879d9674b06578f62ec2f341ddd3b648dfdf51</inline>
+ <curve>cofactor/cofactor163t8</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t8/1</id>
+ <inline>0x04558236ae8cbb8b7f551db9b7ffeba4d05a6925f8,0x07af55a9913a11785b3cd3f8b92d5968273bdbc6a7</inline>
+ <curve>cofactor/cofactor163t8</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t8/2</id>
+ <inline>0x0180ead5cc93652110c10254291c060a6039102f2f,0x01c27f76b0e8f6c445ec14041ad6bf528133b0f5ba</inline>
+ <curve>cofactor/cofactor163t8</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t16/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x04274cf55c49c32ca4c0e30b891e03b3b1c6597df0</inline>
+ <curve>cofactor/cofactor163t16</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t16/1</id>
+ <inline>0x045a5eb7dd5d3a66c37ccc17d1c2cc278c52341311,0x00d335cb03f5cffe4aae83eca0142719ba056b3b91</inline>
+ <curve>cofactor/cofactor163t16</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t16/2</id>
+ <inline>0x02491353f117e84d3bccfdec06dc80881bf4962916,0x07a0e8a86cb7b13b4e7dff9c5a6c2cec2dfe43bd3c</inline>
+ <curve>cofactor/cofactor163t16</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t16/3</id>
+ <inline>0x06ef9e3bc176cc3e4f22734c6b1403a52fcb4f5ded,0x05b854eba0ed2c1b1ba58db768391935bc45008aed</inline>
+ <curve>cofactor/cofactor163t16</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t32/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x0409969efb468e8f07954a3b4bf7610a0d8b5d4753</inline>
+ <curve>cofactor/cofactor163t32</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t32/1</id>
+ <inline>0x0718ffc297e2a28c40b1a99a1243788908bf234788,0x072c98ada87c3d2bd169ebb13484046487389c0aac</inline>
+ <curve>cofactor/cofactor163t32</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t32/2</id>
+ <inline>0x05398dacbc3685efa32fb8073f653a13454bdd84d1,0x04a3c63e84d6c2612d29cc73f8025c678c40fc238b</inline>
+ <curve>cofactor/cofactor163t32</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t32/3</id>
+ <inline>0x04ef69ff0767053e16dc764753dce52e4abd2008af,0x06179a3827cc46bc431e38960d33b9d55d6c589059</inline>
+ <curve>cofactor/cofactor163t32</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t32/4</id>
+ <inline>0x02ee97f9a7d793ce62c74af97a9f096a7572ba69b9,0x000f6d594c47c324daa0e08324367fe6570dea1bf3</inline>
+ <curve>cofactor/cofactor163t32</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t64/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x068c5445c03a59d697573b09ae0804e2891bb98208</inline>
+ <curve>cofactor/cofactor163t64</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t64/1</id>
+ <inline>0x07ebc6a2d17da53c7eb2d1db5b1c8f4bc09cbe0c9a,0x00d8dad45ee9b10d1b9c65e33779a9915dab1bcdca</inline>
+ <curve>cofactor/cofactor163t64</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t64/2</id>
+ <inline>0x06c2e736395e30d258e1d55e99754b13cb95df5a77,0x02c927a236717ee2a0023c2932b581b30e1198ba52</inline>
+ <curve>cofactor/cofactor163t64</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t64/3</id>
+ <inline>0x02d043a910ce708b391974f4bf2d948b2ff9404ac1,0x0173d5211bd148c51a5356125b4e1037287ca76dbf</inline>
+ <curve>cofactor/cofactor163t64</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t64/4</id>
+ <inline>0x00b16f32c64daa847ecbb91ec3df09320b898753e8,0x0386287097ae6bc4fe440c21855dd51cbb063cfa01</inline>
+ <curve>cofactor/cofactor163t64</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t64/5</id>
+ <inline>0x02d3b0a084b4c191d61cccb9906b072946e8167c7c,0x041c5c739372f85d9801de81ceae8610d1d46baa0b</inline>
+ <curve>cofactor/cofactor163t64</curve>
+ <desc>cofactor order = 64</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t128/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x06be374502a948489de2e7d8d82cb6b62a493b77a0</inline>
+ <curve>cofactor/cofactor163t128</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t128/1</id>
+ <inline>0x06c8d7f80b6c2dfbb970c103dbe4823ddadbbc2d44,0x051d1ae93f3798b7d07dc5a42ae10b9ddbe6a27f9e</inline>
+ <curve>cofactor/cofactor163t128</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t128/2</id>
+ <inline>0x070bb18c1a173b81a08312cea7ae8be4e5085bd4e4,0x0196906f241cadfdad35b1e38754b01c1baf7f20da</inline>
+ <curve>cofactor/cofactor163t128</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t128/3</id>
+ <inline>0x02e6190b983edeed23a75c7905e625e9d4d5aab337,0x009be2cfb9d400f20f1ad38963fa756d3beea8b5f1</inline>
+ <curve>cofactor/cofactor163t128</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t128/4</id>
+ <inline>0x01ddf5cb0517f268ac0446ec605c6c9e2f47cad1ad,0x06ff8b935fb64abcaadf9528c164278c4861190399</inline>
+ <curve>cofactor/cofactor163t128</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t128/5</id>
+ <inline>0x03ead0b91adc1e11c6f1aea37993d4aa233f722f16,0x03566f6678f3f63004c084469330c55a54e47152ed</inline>
+ <curve>cofactor/cofactor163t128</curve>
+ <desc>cofactor order = 64</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor163t128/6</id>
+ <inline>0x0597fab16d4fd300694e45e02ce97126d6abfdf527,0x013f75f2b43c53296f06fc584b02ab9b7e5eda28aa</inline>
+ <curve>cofactor/cofactor163t128</curve>
+ <desc>cofactor order = 128</desc>
+ </pubkey>
+
+ <pubkey>
+ <id>cofactor233t2/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x00a5237785bb2d49881f043553257d8600988d9603b43b4c2d74539a7ab3</inline>
+ <curve>cofactor/cofactor233t2</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t4/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x01e70983b7039468a1b58b757d8343c7612f847f51f357ccca6a4c38e774</inline>
+ <curve>cofactor/cofactor233t4</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t4/1</id>
+ <inline>0x01b2130e54e0b949f46bb1a356e4da9b117168171c95bd8f8606dbb841f0,0x00df888613dd7319af9881c87b3b96586a6ea0bc8763e460d1cfad59beeb</inline>
+ <curve>cofactor/cofactor233t4</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t8/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x0087c295986f53382f7f1d4c8f268bdde12c5e2b641e53f84b5c2feb209a</inline>
+ <curve>cofactor/cofactor233t8</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t8/1</id>
+ <inline>0x00a84d10e99cdacf913bc463c64fe963874bd43f7b6285b3328c584f379d,0x0116083d4b7d721cab9f8e28687946775cbe53013974f0d64da6a3753871</inline>
+ <curve>cofactor/cofactor233t8</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t8/2</id>
+ <inline>0x0030b705cd14925afbc424bba3ca2d306e1919228fbdeb69722d778d2fd1,0x01b57b56dfd941a990349cfbe4738049158da63038002b8b66b1958a3f28</inline>
+ <curve>cofactor/cofactor233t8</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t16/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x00c6ff713492ad9d63db4627a4f8d0d67388d85ea20ba5ef234a43ec98d4</inline>
+ <curve>cofactor/cofactor233t16</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t16/1</id>
+ <inline>0x000054b1aeb9f6ec672eda79ea63d50afd64379da32c67b393613e5380a5,0x0007a5bcc9d28b17b3ee8b6c01146b418134d653dac30b9f141cadb8bdf3</inline>
+ <curve>cofactor/cofactor233t16</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t16/2</id>
+ <inline>0x0076e03623260120f8abb528fa31087853a445dd4f4761aa4927d0c435e5,0x011d084efa87e9d129153bcdbc50177015ecfa822ae7b9bcc229b9f57987</inline>
+ <curve>cofactor/cofactor233t16</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t16/3</id>
+ <inline>0x01e334dd359ca817a6b667a95c1c408387869583a7aad103d90dab7f07ab,0x0136e465f537139aad625893172512a06d242474c623003e5f90dd244997</inline>
+ <curve>cofactor/cofactor233t16</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t32/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x00e85ccaafcd345663cb65ccf38555c68183f25b6ec0e436f8f236fe8636</inline>
+ <curve>cofactor/cofactor233t32</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t32/1</id>
+ <inline>0x00027d98a3ee381684443b18bdabf2a8e83b6e99bad701208a688115e418,0x01f167acce102a713f0256da2c6ef68d9162cb45b99bd0d3a579c6996545</inline>
+ <curve>cofactor/cofactor233t32</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t32/2</id>
+ <inline>0x00644243499f513d3541244f49419eaeb3714b641da3fe566d2c1fd04f4e,0x00c6f0694379c25b852bb8e71785912fc3b73275061da6f0e91f50d6aa48</inline>
+ <curve>cofactor/cofactor233t32</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t32/3</id>
+ <inline>0x01eea9c0d7203865aba9d5ef5c8688c8f028222bd8c553ea2a37549ec1af,0x0049a7cf8f926869ebc36e2ff636e5eb7cb1d0406a6e43902bb921859883</inline>
+ <curve>cofactor/cofactor233t32</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t32/4</id>
+ <inline>0x01880fb8975f5024c34bd78dd2d5fbedb724ee288940c6a4ae50c3fe88c2,0x00118b407d962d2c4359f639258526d6c8ed8a1db93034ff34d877b31dd1</inline>
+ <curve>cofactor/cofactor233t32</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t64/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x01a08b13e17f2467daaf4c4f62a397f2393b19c0bfff1dd767f6c8d94860</inline>
+ <curve>cofactor/cofactor233t64</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t64/1</id>
+ <inline>0x0124da33fe559716da4d8fe52bb54490159f2bc3a9c8c832a4cd321db26d,0x01744c31a30ab6b516f3a96f173aef281fbd80d3f35976b50619ffc878c8</inline>
+ <curve>cofactor/cofactor233t64</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t64/2</id>
+ <inline>0x01f956c2aef1da18bc8c21a45e6161dac74aeb8ffc63528c5ddad8d73000,0x00b82ff8a8c62906f80294833d65c8d1e6d6fd1942cd05d88db9c7a7afed</inline>
+ <curve>cofactor/cofactor233t64</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t64/3</id>
+ <inline>0x00f3c42ae0ad4315728635a4fe24ba2a51102a3c4e94bcfbad165a534820,0x005abed4d9649b656824d041650b2bc027db10fe4a7314ea73ae8add6c34</inline>
+ <curve>cofactor/cofactor233t64</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t64/4</id>
+ <inline>0x01d94d241b3b5a14e420f845a5835555efd8b4ac7a859a6b811309a6c525,0x00c2f035151644c52617a436b6aeabb8e50ef6e12fa5b1bd1102c913c72d</inline>
+ <curve>cofactor/cofactor233t64</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t64/5</id>
+ <inline>0x00ebc7a88e760c7932108e6c925b8e8a40cf0f809f2144e772f059cef16c,0x015fe6fec0e1558cf4cc5c73d7d0a8973eb5f7be65cc537c8055e2142c45</inline>
+ <curve>cofactor/cofactor233t64</curve>
+ <desc>cofactor order = 64</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t128/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x0018948e6063085fbc0a661dc0d06bc45c2bbab443e9d983753886b918ea</inline>
+ <curve>cofactor/cofactor233t128</curve>
+ <desc>cofactor order = 2</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t128/1</id>
+ <inline>0x01e41de7ac8dabaa1e873fd528d3c5e462890f60a444a12e1f87902a5f80,0x01148ae9d64a4223ba0bd24d642a6b2cdbbc1358fccd78eea473019a3aa8</inline>
+ <curve>cofactor/cofactor233t128</curve>
+ <desc>cofactor order = 4</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t128/2</id>
+ <inline>0x00e62c29001164bd807f1984bc2d9df15f979f42acf6d10ca6df31ebd8f8,0x00b5e5a686e3a8f87db3c03223322e3d6d0b67ac1d959e3b43a5d66cc734</inline>
+ <curve>cofactor/cofactor233t128</curve>
+ <desc>cofactor order = 8</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t128/3</id>
+ <inline>0x019cf3cd40ee9c3feff8d301ce3b949691d4a1415b89f6e4d2f9799c2071,0x012c90d7c0d2b2a6677cd1015e7611334098c557181080d1e3c4832b7e46</inline>
+ <curve>cofactor/cofactor233t128</curve>
+ <desc>cofactor order = 16</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t128/4</id>
+ <inline>0x00c9fe0dc85e72812aa285b889786c323d2c55de71cf8aa3706c4d5819e1,0x018770dd46a7914c7e8ba6f9babe7a43d489237331fa5d5be1f4a8478d93</inline>
+ <curve>cofactor/cofactor233t128</curve>
+ <desc>cofactor order = 32</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t128/5</id>
+ <inline>0x01a9d88c20ae689f118efc37e85699a87826c224470f2ed075d377505765,0x01d3d88eca62c36c83300658c35cf4c50fb62e4d38b890462db90a7b0892</inline>
+ <curve>cofactor/cofactor233t128</curve>
+ <desc>cofactor order = 64</desc>
+ </pubkey>
+ <pubkey>
+ <id>cofactor233t128/6</id>
+ <inline>0x014ab29589292a78426bd618c99c520a950119e2642302c02e29e4507ccc,0x01ce0273b2fe1e3bdc53116d670ce682d73d0988dc124169dfadd1d1f727</inline>
+ <curve>cofactor/cofactor233t128</curve>
+ <desc>cofactor order = 128</desc>
+ </pubkey>
+
+ &secg;
+
+ <pubkey>
+ <id>pq/cofactor128/1</id>
+ <inline>0x73ca0050dff0de43cff4a026d8aa4baa,0xebd7490611fe3886fe5a8083d344edd0</inline>
+ <curve>composite/pq/composite128/1</curve>
+ <desc>cofactor order = 0x000000003c1be1d1dd7edf84b8013495</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor128/2</id>
+ <inline>0x6ef5b1d42abdbd6f44bcf4d64504927c,0x73e82c27b93032b7a7a15111d1569bb3</inline>
+ <curve>composite/pq/composite128/2</curve>
+ <desc>cofactor order = 0x000000000000000000000003f76917eb</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor160/1</id>
+ <inline>0x0818df9ccebf5b3fd422d00393d346b314e48f98,0x75bde540b81b5bf0ab45c86fbff7bb2e7ec833cb</inline>
+ <curve>composite/pq/composite160/1</curve>
+ <desc>cofactor order = 0x00000000000000000d4d7041e1dbf10b42f48c4f</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor160/2</id>
+ <inline>0x706deef87d4593bbeaa70bc2609e1d8c0e2e0c10,0x64df2537d395da2e0cb8c7e340426b64699cf325</inline>
+ <curve>composite/pq/composite160/2</curve>
+ <desc>cofactor order = 0x00000000000000000000000af2407f270b81f45f</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor192/1</id>
+ <inline>0x6366613b66339fa580f390d630ccf9b535437229aa8b61cd,0x1b975fa3848bd68f34f6a08b7cf190bcaeaf9782270e2413</inline>
+ <curve>composite/pq/composite192/1</curve>
+ <desc>cofactor order = 0x00000000000000000000035efd8bad55038e6bd22db8b805</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor192/2</id>
+ <inline>0x6366613b66339fa580f390d630ccf9b535437229aa8b61cd,0x2abab8c0e803a3612c7a7fbcb47e06fd8ef42a7a7d8c380f</inline>
+ <curve>composite/pq/composite192/2</curve>
+ <desc>cofactor order = 0x00000000000000000000000000302b72431ff070e7e06799</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor224/1</id>
+ <inline>0x97e540c8fc6f9603f25b1689895e5fe738565013675b1bd6c0e16a4b,0x66d0bbe7ee9b0e9e7e1d43b6a47e1d5550c696433c58ee06b94e8615</inline>
+ <curve>composite/pq/composite224/1</curve>
+ <desc>cofactor order = 0x0000000000000000000006a99de2a928e8f227e7a2ed33a555f24ef5</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor224/2</id>
+ <inline>0x1b189f3372946c9cbb421a60bc3a0a06d16cf3ce043781ada561834c,0x57e00f270dbc56c6c86946dcb6c6ab12133d168609c588b6960c357f</inline>
+ <curve>composite/pq/composite224/2</curve>
+ <desc>cofactor order = 0x00000000000000000000000000000000001824ec370e405bfb5024db</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor256/1</id>
+ <inline>0xda63037417b6151b844b2367428f52692f31f14a6654edc58edb5864d0e85ff7,0x8191a142a1c4f913e146af089b1cbe12a803473d207e93697afd1a83818e08be</inline>
+ <curve>composite/pq/composite256/1</curve>
+ <desc>cofactor order = 0x000000000000000220d23234534b240aac0efa70a3bc44e046c2431ad5a32d27</desc>
+ </pubkey>
+ <pubkey>
+ <id>pq/cofactor256/2</id>
+ <inline>0x7b258197e20de13053c3384efd34c3f17172d8ee22c4e23491ca2f867383d8de,0x4aa05d30077ed1bfa45301348e6ab9b1d436f1755c6747c958d4dc24fcb6996c</inline>
+ <curve>composite/pq/composite256/2</curve>
+ <desc>cofactor order = 0x000000000000000000000000000000000000000000000000743bc7ea193d40db</desc>
+ </pubkey>
+</keys>
diff --git a/src/cz/crcs/ectester/data/cofactor/secg_keys.xml b/src/cz/crcs/ectester/data/cofactor/secg_keys.xml
new file mode 100644
index 0000000..d9d3896
--- /dev/null
+++ b/src/cz/crcs/ectester/data/cofactor/secg_keys.xml
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<pubkey>
+ <id>sect163k1/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect163k1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect163k1/1</id>
+ <inline>0x07759edd174e24fd20b34e6d43e51230f0f7f892ab,0x05e4bf4321769ea3f4dc92abe028069f8db0fc0dc1</inline>
+ <curve>secg/sect163k1</curve>
+ <desc>order = 0x800000000000000000004021145c1981b33f14bde</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect163r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x009917a2556e1856bc7ea9a472cd01bfb889b95835</inline>
+ <curve>secg/sect163r1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect163r1/1</id>
+ <inline>0x05a78dd5973d0d39a5970d49b7a13df98558981dcb,0x0340755fa31149f5bf1dd4bf1fa3ef38432babbe13</inline>
+ <curve>secg/sect163r1</curve>
+ <desc>order = 0x7fffffffffffffffffffe91556d1385394e204f36</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect163r2/0</id>
+ <inline>0x000000000000000000000000000000000000000000,0x02c25b85badf8927593d21c366da89c03969f34da5</inline>
+ <curve>secg/sect163r2</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect163r2/1</id>
+ <inline>0x00b8a6683b6d99c044e1086e4eef5d2bd80fd2df41,0x04f6dfa693e7017de96c6e002871b72b3eb6d77b83</inline>
+ <curve>secg/sect163r2</curve>
+ <desc>order = 0x80000000000000000000525fcefce182548469866</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect233k1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect233k1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect233k1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000001,0x000000000000000000000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect233k1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect233k1/2</id>
+ <inline>0x01c90d47aff1ed1172eb861cbc5f11ade07f775b1fdd89b1665c464a97d9,0x002b41324d806a174953fb4ccf8bbeb4fd36cef6f30ccc93618dd282a8e0</inline>
+ <curve>secg/sect233k1</curve>
+ <desc>order = 0x100000000000000000000000000000d3ab7722b79a8ddf635abe2e757be</desc>
+</pubkey>
+<pubkey>
+ <id>sect233k1/3</id>
+ <inline>0x01f477bff0fda3ecd2fa1dff08045717ccf615189375e2437f539c1e1687,0x019f18a66f38eda89284e3979b2aa6ae034cc4a6c7999080815af028bafe</inline>
+ <curve>secg/sect233k1</curve>
+ <desc>order = 0x200000000000000000000000000001a756ee456f351bbec6b57c5ceaf7c</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect233r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x0187f85627b97874e747ee31e06d71caaeea52f21253e5f946d061da9138</inline>
+ <curve>secg/sect233r1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect233r1/1</id>
+ <inline>0x00fe7bac18bdc41b4adbabaaa5dd95e7a170b63bb3519b5d897205fe779f,0x0109d0b6ef40d7f05129ee664be44ae57393716c0233857db6a3358926f7</inline>
+ <curve>secg/sect233r1</curve>
+ <desc>order = 0x2000000000000000000000000000027d2e9ce5f14d244063a4c079fc1ae</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect239k1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect239k1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect239k1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000001,0x000000000000000000000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect239k1</curve>
+ <desc>order = 4</desc>
+</pubkey>
+<pubkey>
+ <id>sect239k1/2</id>
+ <inline>0x2e97f4bf96f4598e4dbbba188895e14b068d9c21ab8e261ffc7d43abc0f2,0x16e86c56595addfdaad811d4bc01df886838cb761332a5bd65f846d63dd3</inline>
+ <curve>secg/sect239k1</curve>
+ <desc>order = 0x400000000000000000000000000000b4f3fd8cf96dd23e383b5001c8f14a</desc>
+</pubkey>
+<pubkey>
+ <id>sect239k1/3</id>
+ <inline>0x718e787b457b7baf3b58bf38c42dd3347802801386fbbe78c4dd5ea31cc0,0x180ad3b3a1182279d21cdd1de3067572c5fe64c3641cc171515c68128cb9</inline>
+ <curve>secg/sect239k1</curve>
+ <desc>order = 0x80000000000000000000000000000169e7fb19f2dba47c7076a00391e294</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect283k1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect283k1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect283k1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000001,0x000000000000000000000000000000000000000000000000000000000000000000000000</inline>
+ <curve>secg/sect283k1</curve>
+ <desc>order = 4</desc>
+</pubkey>
+<pubkey>
+ <id>sect283k1/2</id>
+ <inline>0x07801fcb7c8e5dd6f8c21c60dd7c13cd472dedffe20c3331d084eb4ba32f7b4b13a3510c,0x01960ead4b2a835d27a626fab5fc6e779b511c680a5e6af9b42d67228261a2add4220335</inline>
+ <curve>secg/sect283k1</curve>
+ <desc>order = 0x3ffffffffffffffffffffffffffffffffffd35c5da0eaee4cbbfeff288a3c0c3c2c78c2</desc>
+</pubkey>
+<pubkey>
+ <id>sect283k1/3</id>
+ <inline>0x00896ce7c7065cc160ca721127910f598edc8b1e9be077d4756f31aee5705a00302d2e1d,0x0381c6394dbf16cf75f9e79c830e57e5a398ba77258e6d224692940eb925ec0b78ece889</inline>
+ <curve>secg/sect283k1</curve>
+ <desc>order = 0x7ffffffffffffffffffffffffffffffffffa6b8bb41d5dc9977fdfe511478187858f184</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect283r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000,0x072bcc9c5792b1ebe81983089fb6f835a2fd220a304424ca17c082ae17442aede9b9b3f6</inline>
+ <curve>secg/sect283r1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect283r1/1</id>
+ <inline>0x0743efa0a997ab11f696f61403759fa6dac093afe26160fa6d4620dc10c73ecbd07d868d,0x013abc297e8c6568601a70a323208d22730b654374643683bb913daaf0910ff492cfb1c5</inline>
+ <curve>secg/sect283r1</curve>
+ <desc>order = 0x7ffffffffffffffffffffffffffffffffffdf20732cc1f92715202cb60854f9df5b660e</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect409k1/0</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect409k1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect409k1/1</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect409k1</curve>
+ <desc>order = 4</desc>
+</pubkey>
+<pubkey>
+ <id>sect409k1/2</id>
+ <inline>0x013b10b72703d774f4873f985742cce57b9377e5f89049e493eac66748870f718ae0f3ae227b6d75f7e5f810d91da79f985cefdc,0x001aea0d33e0ae234db866482308cbc579e9c7cab1fad1b62dac2a3ea16bec7ca504da1d86370fc748d1ddbc443c8a920c7b9d14</inline>
+ <curve>secg/sect409k1</curve>
+ <desc>order = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffcbf0765a9d440801d88aafabda7c7cf94b696b90771c03cbf9e</desc>
+</pubkey>
+<pubkey>
+ <id>sect409k1/3</id>
+ <inline>0x00a6cc45b0ed549286beb3f391467dcd5106fed4fb850e0ca45ac7a5291fa1f73c2ebd66b5eb2fc6c3ad93a225c20e29d76172e1,0x019c34bda5074fe8c75e1017d8b64a87766467083fb6e17a4fc57ca39c6801a31eb71e824fa225922e361db0946c4a3e7445468d</inline>
+ <curve>secg/sect409k1</curve>
+ <desc>order = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffff97e0ecb53a881003b1155f57b4f8f9f296d2d720ee380797f3c</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect409r1/0</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x009935f7e4768ee2ef22f9b4a29f53cb5d93ab2ed0ad7ce57c1b2649fde895950cf6576773326c528a48e27b872accf0bc25d5ef</inline>
+ <curve>secg/sect409r1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect409r1/1</id>
+ <inline>0x01f8a55ff6e55b1d023eca11efc629aedba15e7683f948a84ef6e3746470b2fe9f9c694f862714ec8dbb35ae8e5b760f488ae84a,0x00c0bbc113adacdb9815bb210178b081ef4b40c949fe52345ad21eab210667cc10b5ac0e60d7bb44fee1d6c544b3cc3a18ad0a23</inline>
+ <curve>secg/sect409r1</curve>
+ <desc>order = 0x20000000000000000000000000000000000000000000000000003c555ad4c25e6660f7cbf48f8793c0a5f0702c99a6fb34422e6</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect571k1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001</inline>
+ <curve>secg/sect571k1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect571k1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</inline>
+ <curve>secg/sect571k1</curve>
+ <desc>order = 4</desc>
+</pubkey>
+<pubkey>
+ <id>sect571k1/2</id>
+ <inline>0x0311efd68e031548397fd197f3c9ea9ef2048b3835bbb52c06cc89fa29a609be1a4215805132ed6c30ed743e6221f34c5d43acd3777c88a42578a7b02d2a9af488c138b206832707,0x01692831faeb78797365873933fd9c5f5223d2bceba37aa6a4f6d128973e3263b124300568f039541e51c6214409523179aaecdf76e789921d84e12991113eacd03727d4c9754920</inline>
+ <curve>secg/sect571k1</curve>
+ <desc>order = 0x400000000000000000000000000000000000000000000000000000000000000000000002630a1c3e334c7c9672351b722fe82716c61b097cbac72703d23bd68b9fcef1ec6f82002</desc>
+</pubkey>
+<pubkey>
+ <id>sect571k1/3</id>
+ <inline>0x0519146e2a901338dce58310d786d30fd6806c620f6a7a9ba4389534dcdf16c6becdacb853fad56e4b048465b4037450468fb9bc6259448ce84a92fd8bfe9c3663dad3da48089517,0x05671e892895ca17683107f21da7741a3fdf47e546dfc6b6d2ed83c970ac88c33b7b522b0a1fe9a7dda46a7075d4881e88b9fc7f3a2002883f6c7d651f9c94252340b59b8abc0aeb</inline>
+ <curve>secg/sect571k1</curve>
+ <desc>order = 0x800000000000000000000000000000000000000000000000000000000000000000000004c614387c6698f92ce46a36e45fd04e2d8c3612f9758e4e07a477ad173f9de3d8df04004</desc>
+</pubkey>
+
+<pubkey>
+ <id>sect571r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0732d556640c20b5dd739a058dffd58268d41c59135429eb041d7aa1255902e6362c4800a874ab0b60536b58460cd20c06f0340e3594a7f771bedfc10ce39b64699b08443b761c43</inline>
+ <curve>secg/sect571r1</curve>
+ <desc>order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>sect571r1/1</id>
+ <inline>0x01e4b7514be19101ec1d9f032bdba65dd1d73465bc1425e3847f44b7b2c78669358ab7bb34dec5202db32c0e65f8f4e0c5c0db8ae19537307ba6391dfa7831375b1b3957d403477a,0x00f04eb4a9ce0f18f879143faea24107682602d9319105a62c2758da491014ae34280a32830a1e239d0e89b3a3ff60acb640afc01aa56dcb8344423f0ad9f071af3d95d7675578fc</inline>
+ <curve>secg/sect571r1</curve>
+ <desc>order = 0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffccc39c31feab30e6100b3630d0470a3d8fbb39422c3bd27aa2e9acdd0705d3765fd09c8e</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/carmichael_128.csv b/src/cz/crcs/ectester/data/composite/carmichael_128.csv
new file mode 100644
index 0000000..400abca
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/carmichael_128.csv
@@ -0,0 +1 @@
+0x8d4731c77d3462993d75627d4ea254ef,0x7374f7d098c61f64d0dcd328b537e22c,0x3658ca99638dc513932535134f48536b,0x7d5beaa13395695173e3371b7638347a,0x6f1c533a21abb60316bb9529528910c4,0x8d4731c77d346297e54306afea3730a1,0x01
diff --git a/src/cz/crcs/ectester/data/composite/carmichael_192.csv b/src/cz/crcs/ectester/data/composite/carmichael_192.csv
new file mode 100644
index 0000000..7c21982
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/carmichael_192.csv
@@ -0,0 +1 @@
+0x8b72c1f15aacdcc4c3d881b3e14fa5e07f614ffd25613c95,0x4de73fecdd02978832f2025306474f85af670aa44735bec4,0x55fa4ea6cbf5241ff5c3734bef8db6399fa45ffbf6450f45,0x0236516a5b59cd7871ed1403e820f07d1795483b5c1cc7c7,0x137236f344d2e6e51476662acc70a2247f81d4801b0b9fa4,0x8b72c1f15aacdcc4c3d881b2a6256f87e98d12e5385af0b9,0x01
diff --git a/src/cz/crcs/ectester/data/composite/carmichael_224.csv b/src/cz/crcs/ectester/data/composite/carmichael_224.csv
new file mode 100644
index 0000000..d72a30c
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/carmichael_224.csv
@@ -0,0 +1 @@
+0x929fe6161bc19ea029efb679c883576d18d69b5b3a3870eaf80d49a3,0x159ef3437e3d7297247f6ad693c1d80f069cb9eb98a0c679668e5ff9,0x6448a16b4ed54d4532e4145cb5fa9a0cd623232d350f706742aeac8c,0x816e1a2510e83da094374558ba2df28976404fcff6c18bfb5eb8cbf9,0x78f245d80d0e1e18e73272fef47911883ae1ab2af985f93f06dbc002,0x929fe6161bc19ea029efb679c881d967bd62678011c1949852a0b119,0x01
diff --git a/src/cz/crcs/ectester/data/composite/carmichael_256.csv b/src/cz/crcs/ectester/data/composite/carmichael_256.csv
new file mode 100644
index 0000000..fea4281
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/carmichael_256.csv
@@ -0,0 +1 @@
+0x974a679ba3168a019e1f069aac82c999e2612f1957052c56607e8002ef36be53,0x51f15e6797f0a4f0f049b1aedb340118e9584727c5668fe856ad8e2fa111f12d,0x4e7c9daa52715b65db00a3f85ec87bf6a8cc1c312845fc302fc724eb0067d82e,0x6737dcaa9b8198f73599b700e6b3bfda05731528b620f9080799fd6d491be926,0x0f71d01a2ac0f12fe6db25cc420578e9acb729d007580b139cb4897d6421517c,0x974a679ba3168a019e1f069aac82c9986c8ed1c88f1d90e54250abfb0a363941,0x01
diff --git a/src/cz/crcs/ectester/data/composite/carmichael_384.csv b/src/cz/crcs/ectester/data/composite/carmichael_384.csv
new file mode 100644
index 0000000..3002514
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/carmichael_384.csv
@@ -0,0 +1 @@
+0xa10402c0f3ab3f57b7ddf22e1b7054a8b2a292e3466496d060a5264d9fe29e2fc22347b3b6c21cdf7cba591fd00abd29,0x3dafe0a9c8fb6540cfb52253c08d63742c122062d031f96b0d901d27c9a91d9cefc6d5df27b9f56664860d02b98bc00c,0x3ae6993a790b7e73d67d1cd3a1376c08b9effb7a43211cd169d4e5871bdf096827d953a9f1a98ad11748b22dadf28f07,0x2f2843692b78f89332597df8bec5f5c55767af145ade2c4ad6a4e08fc772c5b7e2bab7d1cb054ebee4367739fe5d5e5c,0x6940f0d9cd2276b4c909e730cdb909a8742a2abee52fe157ca7401d1d825f57145a3cc20522910b28b90cffc38d64e9b,0xa10402c0f3ab3f57b7ddf22e1b7054a8b2a292e3466496d056717d18f11d70554d3bff46c2b156dc594b563cf7ce93d1,0x01
diff --git a/src/cz/crcs/ectester/data/composite/carmichael_512.csv b/src/cz/crcs/ectester/data/composite/carmichael_512.csv
new file mode 100644
index 0000000..59d0b03
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/carmichael_512.csv
@@ -0,0 +1 @@
+0x9c4dc6f1cd53c38d5af75215620fb6d643257fb1f658d3e5d3b5412dee1bce65b734e62f7a592cda1f6218a11d07f791503e00190b94521255c291e59a069367,0x624745292ab68c1d121cc5f7bda57be0be0fc2461c212494d44f4d522bf797f31c47ba99b44c7145313aebe5bb03893ed11cfc926082e51426cc2b4347746aa5,0x456e5b484249ffa61273c26a91941dd9f1153b4e972df10cfe7c32c64f8aa6ac0f9ec02b63dec7daff1f30eb1a5ac7b641671092f723175f092f13e5f41f1399,0x4348b5167f4f5d7c3d1265d5f08e08db97cd506b9b2e546d94065220597e79291c2c2ece0f6b904a2a8c39f3adc6706724b56dc26804e19e5fefce5a7763d241,0x61bc72b13f6954704e8d219c2d1a20824dc759503f49b8aed3de1acb1761d68a68fbc93064ba12cac87344690be9027e763e3889ae561904c68bc586407018db,0x9c4dc6f1cd53c38d5af75215620fb6d643257fb1f658d3e5d3b5412dee1bce670a65fd73b857d9d8111f52eb305cfc13d96ca09cdc88e257b289d02d3239d259,0x01
diff --git a/src/cz/crcs/ectester/data/composite/carmichael_521.csv b/src/cz/crcs/ectester/data/composite/carmichael_521.csv
new file mode 100644
index 0000000..47ec1c3
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/carmichael_521.csv
@@ -0,0 +1 @@
+0x011ebb4ebb42f370324a2b937a20c443f110e1e3c40ecb3eb63af873d0c86e7cce05e5416605f1fcfc8296c879bbea344084007bb8fc2c704d85fc4b7fcdc0a4a001,0x00be420c826bac034b4b24ba623a2551510f6663babc95d6741dd68ab05adf6cf2624b1d47fb76c7b0b3edae8c436befe0b5d536525bd662e911529d00c05437e1db,0x0087789843e5da542f34b7c9737db3f6dbaf515788f355b0e2e36d66eb65d1a183a95a88fb9ffa27807961581ed69473046df573baab472fca6a361228bf326fa7f7,0x00457d321b63688cff7ddb0c04fb4bec1b0da6b5af8cac11b9d6fdce431e80d4b48947329078a7c1c5ca9aeb351a2514f89ef8215adaad9af4f581df098fa088aba6,0x00c286d2f1e48e58787c83878624b273db0fa6c3de13e59e326c0f783a40056dd3623688156396986179d5ee97cf9df846ac7a3180a27a23a45cbb400d9553d8a659,0x11ebb4ebb42f370324a2b937a20c443f110e1e3c40ecb3eb63af873d0c86e7cce1752f780ce79d0886704c8603b16dbb491481c1b6682865a9b7f83440515fbe561,0x01
diff --git a/src/cz/crcs/ectester/data/composite/composite128_pq.csv b/src/cz/crcs/ectester/data/composite/composite128_pq.csv
new file mode 100644
index 0000000..8aea6b2
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite128_pq.csv
@@ -0,0 +1 @@
+0xee6b3964632807cf11b8b9dba1b4f099,0x1fd6f78c0303652c5b7de184a4744f98,0x2da1b3253571565989f3b72b865a3e27,0x7c23e2a7e80b6586a1f9e1c9d4fbadc2,0xe987ee5eb715e2eb8cc8ad77311cfe0a,0xee6b3964632807cd9c885b5658f1a7c7,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite128_pq1.csv b/src/cz/crcs/ectester/data/composite/composite128_pq1.csv
new file mode 100644
index 0000000..a551487
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite128_pq1.csv
@@ -0,0 +1 @@
+0xee6b3964632807cf11b8b9dba1b4f099,0x1fd6f78c0303652c5b7de184a4744f98,0x2da1b3253571565989f3b72b865a3e27,0x6ef5b1d42abdbd6f44bcf4d64504927c,0x73e82c27b93032b7a7a15111d1569bb3,0x000000000000000000000003f76917eb,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite128_pq2.csv b/src/cz/crcs/ectester/data/composite/composite128_pq2.csv
new file mode 100644
index 0000000..69181df
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite128_pq2.csv
@@ -0,0 +1 @@
+0xee6b3964632807cf11b8b9dba1b4f099,0x1fd6f78c0303652c5b7de184a4744f98,0x2da1b3253571565989f3b72b865a3e27,0x73ca0050dff0de43cff4a026d8aa4baa,0xebd7490611fe3886fe5a8083d344edd0,0x000000003c1be1d1dd7edf84b8013495,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite128_rg0.csv b/src/cz/crcs/ectester/data/composite/composite128_rg0.csv
new file mode 100644
index 0000000..2e039f4
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite128_rg0.csv
@@ -0,0 +1 @@
+0xee6b3964632807cf11b8b9dba1b4f099,0x1fd6f78c0303652c5b7de184a4744f98,0x2da1b3253571565989f3b72b865a3e27,0x6ef5b1d42abdbd6f44bcf4d64504927c,0x73e82c27b93032b7a7a15111d1569bb3,0xee6b3964632807cd9c885b5658f1a7c7,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite128_small.csv b/src/cz/crcs/ectester/data/composite/composite128_small.csv
new file mode 100644
index 0000000..fbcbdca
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite128_small.csv
@@ -0,0 +1 @@
+0xc8bb039faeca04585e1d5864fbc05f6b,0x90af1043a837133b556495fe1e080b7c,0x916d1eaf6cc9eee0f86e5bd6313ba6fc,0x746fa441b3a54d3c531bd59d119f400d,0x73aff68dbd96e1485cd2de0f6389cc70,0x00000000000000000000000000000003,0x1 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite160_pq.csv b/src/cz/crcs/ectester/data/composite/composite160_pq.csv
new file mode 100644
index 0000000..3f43b50
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite160_pq.csv
@@ -0,0 +1 @@
+0x919cf0a89ca7a8ea2f61156ea4b3100a2a357477,0x75cd1f1c32f1e5d2b2d54db103b22d296de34722,0x3177d3e2f79c884a0b1a6e74d9843c3a52e794de,0x46239bb42c524f45764e8edba8c958203d185886,0x6bce8ab48c9b4d0ab4083122ea9684173f9b07a9,0x919cf0a89ca7a8ea2f626ab2ab86ff4a074a5d51,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite160_pq1.csv b/src/cz/crcs/ectester/data/composite/composite160_pq1.csv
new file mode 100644
index 0000000..debd466
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite160_pq1.csv
@@ -0,0 +1 @@
+0x919cf0a89ca7a8ea2f61156ea4b3100a2a357477,0x75cd1f1c32f1e5d2b2d54db103b22d296de34722,0x3177d3e2f79c884a0b1a6e74d9843c3a52e794de,0x706deef87d4593bbeaa70bc2609e1d8c0e2e0c10,0x64df2537d395da2e0cb8c7e340426b64699cf325,0x00000000000000000000000af2407f270b81f45f,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite160_pq2.csv b/src/cz/crcs/ectester/data/composite/composite160_pq2.csv
new file mode 100644
index 0000000..efd7475
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite160_pq2.csv
@@ -0,0 +1 @@
+0x919cf0a89ca7a8ea2f61156ea4b3100a2a357477,0x75cd1f1c32f1e5d2b2d54db103b22d296de34722,0x3177d3e2f79c884a0b1a6e74d9843c3a52e794de,0x0818df9ccebf5b3fd422d00393d346b314e48f98,0x75bde540b81b5bf0ab45c86fbff7bb2e7ec833cb,0x00000000000000000d4d7041e1dbf10b42f48c4f,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite160_rg0.csv b/src/cz/crcs/ectester/data/composite/composite160_rg0.csv
new file mode 100644
index 0000000..e6a1a95
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite160_rg0.csv
@@ -0,0 +1 @@
+0x919cf0a89ca7a8ea2f61156ea4b3100a2a357477,0x75cd1f1c32f1e5d2b2d54db103b22d296de34722,0x3177d3e2f79c884a0b1a6e74d9843c3a52e794de,0x706deef87d4593bbeaa70bc2609e1d8c0e2e0c10,0x64df2537d395da2e0cb8c7e340426b64699cf325,0x919cf0a89ca7a8ea2f626ab2ab86ff4a074a5d51,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite160_small.csv b/src/cz/crcs/ectester/data/composite/composite160_small.csv
new file mode 100644
index 0000000..2adaa8b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite160_small.csv
@@ -0,0 +1 @@
+0x9b0bafb73969e379b49753fa1b3cc65e9ca73adf,0x93091909c640bcdf66f470c1627ec776e9f625cc,0x69c34611c6d4cb088365ae95bf2d7d9c97aaf224,0x68684425389f5552a24b7c205e19da7a0c10a1cb,0x825ecf13c08f314cd6ad5eae73044c71e9876409,0x0000000000000000000000000000000000000003,0x1 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite192_pq.csv b/src/cz/crcs/ectester/data/composite/composite192_pq.csv
new file mode 100644
index 0000000..47b8a13
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite192_pq.csv
@@ -0,0 +1 @@
+0xa261fff62647eebf810a404f0c80a971dd7c7838fdc52b5b,0x87502ebb62d26e1eca06c434f8ef069dfb2c287d6183750c,0x4ad6ce1f16e1bfc3d40f0027d787aeadb53846d69099a883,0x253e1db7210418abfe1de82c0053098e90bb15ad4f20096f,0x962c565cb0dd62b6a04be33ec7b20a1b3e7f23e24d48c6c2,0xa261fff62647eebf810a404f23ba4db93199e2e02ccffdfd,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite192_pq1.csv b/src/cz/crcs/ectester/data/composite/composite192_pq1.csv
new file mode 100644
index 0000000..664d35e
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite192_pq1.csv
@@ -0,0 +1 @@
+0xa261fff62647eebf810a404f0c80a971dd7c7838fdc52b5b,0x87502ebb62d26e1eca06c434f8ef069dfb2c287d6183750c,0x4ad6ce1f16e1bfc3d40f0027d787aeadb53846d69099a883,0x6366613b66339fa580f390d630ccf9b535437229aa8b61cd,0x2abab8c0e803a3612c7a7fbcb47e06fd8ef42a7a7d8c380f,0x00000000000000000000000000302b72431ff070e7e06799,0x1 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite192_pq2.csv b/src/cz/crcs/ectester/data/composite/composite192_pq2.csv
new file mode 100644
index 0000000..33fe0f3
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite192_pq2.csv
@@ -0,0 +1 @@
+0xa261fff62647eebf810a404f0c80a971dd7c7838fdc52b5b,0x87502ebb62d26e1eca06c434f8ef069dfb2c287d6183750c,0x4ad6ce1f16e1bfc3d40f0027d787aeadb53846d69099a883,0x6366613b66339fa580f390d630ccf9b535437229aa8b61cd,0x1b975fa3848bd68f34f6a08b7cf190bcaeaf9782270e2413,0x00000000000000000000035efd8bad55038e6bd22db8b805,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite192_rg0.csv b/src/cz/crcs/ectester/data/composite/composite192_rg0.csv
new file mode 100644
index 0000000..a55a994
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite192_rg0.csv
@@ -0,0 +1 @@
+0xa261fff62647eebf810a404f0c80a971dd7c7838fdc52b5b,0x87502ebb62d26e1eca06c434f8ef069dfb2c287d6183750c,0x4ad6ce1f16e1bfc3d40f0027d787aeadb53846d69099a883,0x6366613b66339fa580f390d630ccf9b535437229aa8b61cd,0x2abab8c0e803a3612c7a7fbcb47e06fd8ef42a7a7d8c380f,0xa261fff62647eebf810a404f23ba4db93199e2e02ccffdfd,0x1 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite192_small.csv b/src/cz/crcs/ectester/data/composite/composite192_small.csv
new file mode 100644
index 0000000..a90364d
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite192_small.csv
@@ -0,0 +1 @@
+0xabe758cde9fc09b714f543b4acac1550c09297279d4d2a1f,0x41e9bf05575d991e1e3393fc1746f2eb49e7f9b34867343e,0x54c5db9d913d1afeabce6e11ea623f8536dd6eef8eb5dfff,0x94863540fdd9e8f415df79e18aee4bdd0914127581b6bb15,0x3aa760e488d12f8f93b10da531e1dbc033db25729119839f,0x000000000000000000000000000000000000000000000003,0x1 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite224_pq.csv b/src/cz/crcs/ectester/data/composite/composite224_pq.csv
new file mode 100644
index 0000000..ffa2cc1
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite224_pq.csv
@@ -0,0 +1 @@
+0xa0dccd401872aa37c279e2469a08d97d559addb6fc870a1766f80e6f,0x393797f1d924dc63c761d4497086d09284a922a5517c07f93f3a075c,0x54f4673322854dafc1241b66192134ea9e18f8849c45660b793abb97,0x4f3b94b4e9234f3611bfe74d69ad06178e06c5f56fa100233f0d43e1,0x0eb042a295465c53ca6e01ff8c2cf4d029bf6d4a646fed830468d73a,0xa0dccd401872aa37c279e2469a0791ea2f15e32a10632ec07cf3ff97,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite224_pq1.csv b/src/cz/crcs/ectester/data/composite/composite224_pq1.csv
new file mode 100644
index 0000000..6a01e2d
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite224_pq1.csv
@@ -0,0 +1 @@
+0xa0dccd401872aa37c279e2469a08d97d559addb6fc870a1766f80e6f,0x393797f1d924dc63c761d4497086d09284a922a5517c07f93f3a075c,0x54f4673322854dafc1241b66192134ea9e18f8849c45660b793abb97,0x1b189f3372946c9cbb421a60bc3a0a06d16cf3ce043781ada561834c,0x57e00f270dbc56c6c86946dcb6c6ab12133d168609c588b6960c357f,0x00000000000000000000000000000000001824ec370e405bfb5024db,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite224_pq2.csv b/src/cz/crcs/ectester/data/composite/composite224_pq2.csv
new file mode 100644
index 0000000..f8bc6df
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite224_pq2.csv
@@ -0,0 +1 @@
+0xa0dccd401872aa37c279e2469a08d97d559addb6fc870a1766f80e6f,0x393797f1d924dc63c761d4497086d09284a922a5517c07f93f3a075c,0x54f4673322854dafc1241b66192134ea9e18f8849c45660b793abb97,0x97e540c8fc6f9603f25b1689895e5fe738565013675b1bd6c0e16a4b,0x66d0bbe7ee9b0e9e7e1d43b6a47e1d5550c696433c58ee06b94e8615,0x0000000000000000000006a99de2a928e8f227e7a2ed33a555f24ef5,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite224_rg0.csv b/src/cz/crcs/ectester/data/composite/composite224_rg0.csv
new file mode 100644
index 0000000..835676d
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite224_rg0.csv
@@ -0,0 +1 @@
+0xa0dccd401872aa37c279e2469a08d97d559addb6fc870a1766f80e6f,0x393797f1d924dc63c761d4497086d09284a922a5517c07f93f3a075c,0x54f4673322854dafc1241b66192134ea9e18f8849c45660b793abb97,0x1b189f3372946c9cbb421a60bc3a0a06d16cf3ce043781ada561834c,0x57e00f270dbc56c6c86946dcb6c6ab12133d168609c588b6960c357f,0xa0dccd401872aa37c279e2469a0791ea2f15e32a10632ec07cf3ff97,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite224_small.csv b/src/cz/crcs/ectester/data/composite/composite224_small.csv
new file mode 100644
index 0000000..ea18b96
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite224_small.csv
@@ -0,0 +1 @@
+0xe6cacc569ea2a63aea0409959625c8f8238b0ddc2565046db20390ed,0x20484bda40fdcade9ff6f9147076e2824e5f0d057a4a95cfb1b9312d,0x14cacbe6ad4a700a3f6a44cdc0a60d6fd0a4f2052c5b9ae5661fd964,0xb4fbabc7cf96b62b08edbaa2df53346bbb871c121bbb35e771c74db5,0x61cf8b556f068f45ec69963964a0e8ab72c1fa0be48e2ea886235956,0x00000000000000000000000000000000000000000000000000000003,0x1 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite256_pq.csv b/src/cz/crcs/ectester/data/composite/composite256_pq.csv
new file mode 100644
index 0000000..380f756
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite256_pq.csv
@@ -0,0 +1 @@
+0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x4c4765a35cb2de9cc548d4dd47778b70395d023c4bf112f4bc820431502384e9,0x25bffa1f9ae1af10177f32abf13d3f607e78415c89676eeb13330098c9794503,0xf75e78a6e2acb23d6317e57258287c021fa26f10c359320ee8758b4e1f2c605d,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite256_pq1.csv b/src/cz/crcs/ectester/data/composite/composite256_pq1.csv
new file mode 100644
index 0000000..9ac845f
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite256_pq1.csv
@@ -0,0 +1 @@
+0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x7b258197e20de13053c3384efd34c3f17172d8ee22c4e23491ca2f867383d8de,0x4aa05d30077ed1bfa45301348e6ab9b1d436f1755c6747c958d4dc24fcb6996c,0x000000000000000000000000000000000000000000000000743bc7ea193d40db,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite256_pq2.csv b/src/cz/crcs/ectester/data/composite/composite256_pq2.csv
new file mode 100644
index 0000000..b8b5e9b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite256_pq2.csv
@@ -0,0 +1 @@
+0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0xda63037417b6151b844b2367428f52692f31f14a6654edc58edb5864d0e85ff7,0x8191a142a1c4f913e146af089b1cbe12a803473d207e93697afd1a83818e08be,0x000000000000000220d23234534b240aac0efa70a3bc44e046c2431ad5a32d27,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite256_rg0.csv b/src/cz/crcs/ectester/data/composite/composite256_rg0.csv
new file mode 100644
index 0000000..0c2d123
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite256_rg0.csv
@@ -0,0 +1 @@
+0xf75e78a6e2acb23d6317e57258287c00597e24881e0686039d0badb77b4e6b21,0x1aafadea1da31b45bbc02da735cc341f9cf9915884eb9cd31441520ead906b38,0x0f7f209988b0eada7190201ace3b3972d6ce3cbadac9933716d08645a7c31c63,0x93d1f4d02d6f0d2ea7b80f7095e70e731bcf66fb8118e7698a16eab45aadcaa4,0x51dccaa47e35062383e4878625bf2116be5413c34a1b964c7547f65297f0bc04,0xf75e78a6e2acb23d6317e57258287c021fa26f10c359320ee8758b4e1f2c605d,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite256_small.csv b/src/cz/crcs/ectester/data/composite/composite256_small.csv
new file mode 100644
index 0000000..58c0a75
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite256_small.csv
@@ -0,0 +1 @@
+0xdc42862158cdcfc8fbe8c4ec28b02e0e12624ebc15f6486163df218253e1b953,0x01f355375dac7e69cc12c22ce747782bf998252f1c9c9c983273bc2b7e721461,0x22098140e10d5d88bcc96a558500a022d0252bfbe438d3475ef2d90261fe3b1f,0x8ca20dd1fa045339a171513fb1daa25fa7439e4b97c129c6039e4b9abbac1532,0xb565bde8fe9831f0bce07d70784dc1b7064c443b54b5e96408c1942e30437cc3,0x0000000000000000000000000000000000000000000000000000000000000005,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite384.csv b/src/cz/crcs/ectester/data/composite/composite384.csv
index 7516301..4e9d058 100644
--- a/src/cz/crcs/ectester/data/composite/composite384.csv
+++ b/src/cz/crcs/ectester/data/composite/composite384.csv
@@ -1 +1 @@
-0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189da10277423d7381fd4671fc706ff1dce6f8513317842fb655b,0x6c64adff869b4e0b9f0dd35945b24e3ab389232b1e506a71306e389dddbf43ec6c73d290fab04976da246fd77a7e28dd,0x4004c33e4f8b4de57064543802ca11810c79aa9990796d5750dba07f3e4e98f3dd18b3abe052208741149c3ad0fe6f56,0x39bf2e7d67ad506e074e04c1b73a4add511b0579cdae07bd6c025c703ee31ff33c0445c2cb10e465f0f453d996751e4e,0x667ec38866be3e87229e31e6dabc2444e2603e8118c0316e592571e9a904423e4792c18c0360ae57fcdaec87901d2e0b,0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189db347c42a7d0924b7cd1414d57f582a4b96177c911e9bb3ddd,0x1 \ No newline at end of file
+0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189da10277423d7381fd4671fc706ff1dce6f8513317842fb655b,0x6c64adff869b4e0b9f0dd35945b24e3ab389232b1e506a71306e389dddbf43ec6c73d290fab04976da246fd77a7e28dd,0x4004c33e4f8b4de57064543802ca11810c79aa9990796d5750dba07f3e4e98f3dd18b3abe052208741149c3ad0fe6f56,0x39bf2e7d67ad506e074e04c1b73a4add511b0579cdae07bd6c025c703ee31ff33c0445c2cb10e465f0f453d996751e4e,0x667ec38866be3e87229e31e6dabc2444e2603e8118c0316e592571e9a904423e4792c18c0360ae57fcdaec87901d2e0b,0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189db347c42a7d0924b7cd1414d57f582a4b96177c911e9bb3ddd,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite384_small.csv b/src/cz/crcs/ectester/data/composite/composite384_small.csv
new file mode 100644
index 0000000..00b643b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite384_small.csv
@@ -0,0 +1 @@
+0x91520c5e44d7a5e9c673943d2fc502d2b35a1c9edc6189da10277423d7381fd4671fc706ff1dce6f8513317842fb655b,0x6c64adff869b4e0b9f0dd35945b24e3ab389232b1e506a71306e389dddbf43ec6c73d290fab04976da246fd77a7e28dd,0x4004c33e4f8b4de57064543802ca11810c79aa9990796d5750dba07f3e4e98f3dd18b3abe052208741149c3ad0fe6f56,0x5136c182f03241ec87e6eec1728c1fb2d6b2ddcd4d9abf2a110c337419c4ec7cc8386b7b9ea9f5cb18b0f3c2a78e6489,0x9130cb73f8064fddb24d8c6a216b57fe99df93bcc82c93343617a5246ca1643fe57a06d6112a1791d1bd3643fbd9c041,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite521.csv b/src/cz/crcs/ectester/data/composite/composite521.csv
index 0cf36e7..8681273 100644
--- a/src/cz/crcs/ectester/data/composite/composite521.csv
+++ b/src/cz/crcs/ectester/data/composite/composite521.csv
@@ -1 +1 @@
-0x01c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b3690e2f82b38a684e823a257b3d5c4c2d7c34bfcb937fe5658c77247b28bc90c6af,0x00852cf32173a9b3a8a2316bbe6ba0b98efcc41247a17a8aead02ccc7cb90870daccd10a44e9385abf0d0ae175fa03c0facab1d2069b79795f36d10ce25430676805,0x0174e20e49d5970117cdfc61c0a0ae062519c0c4d577f42e0d3f1cd443732b8e62deb34922a4a6d85b8b7f6df61dadffec95c17babbfaf5c57598033be0b1a44e32f,0x01b1dbc5bd175cbd8699895698b10d047853679f048261094854134de1d6a81ffdd1cc31ede64293c9bee543ad2113c164bd1da92f5c3aa7ba7f0378bdb58251d870,0x0188b8c020cc1504eedb4fb859e40b8031cb26d9273efa2578bf7da01db994cf2a5cf2780b9a7ff6d33210b962ae20c56f71b7fa2b36deef33d7d675c6136acd73c1,0x1c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b36ec447771e871c188d3f04a4e407f1d659335dd0e351bd7f3f76a639726d6dc0d2,0x1 \ No newline at end of file
+0x01c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b3690e2f82b38a684e823a257b3d5c4c2d7c34bfcb937fe5658c77247b28bc90c6af,0x00852cf32173a9b3a8a2316bbe6ba0b98efcc41247a17a8aead02ccc7cb90870daccd10a44e9385abf0d0ae175fa03c0facab1d2069b79795f36d10ce25430676805,0x0174e20e49d5970117cdfc61c0a0ae062519c0c4d577f42e0d3f1cd443732b8e62deb34922a4a6d85b8b7f6df61dadffec95c17babbfaf5c57598033be0b1a44e32f,0x01b1dbc5bd175cbd8699895698b10d047853679f048261094854134de1d6a81ffdd1cc31ede64293c9bee543ad2113c164bd1da92f5c3aa7ba7f0378bdb58251d870,0x0188b8c020cc1504eedb4fb859e40b8031cb26d9273efa2578bf7da01db994cf2a5cf2780b9a7ff6d33210b962ae20c56f71b7fa2b36deef33d7d675c6136acd73c1,0x1c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b36ec447771e871c188d3f04a4e407f1d659335dd0e351bd7f3f76a639726d6dc0d2,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/composite521_small.csv b/src/cz/crcs/ectester/data/composite/composite521_small.csv
new file mode 100644
index 0000000..15df9c8
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/composite521_small.csv
@@ -0,0 +1 @@
+0x01c230ff4a64e33ad6da8361c7e2bf2a85e4ad5e88f8e3e8e7e3c42a6b9c9883b3690e2f82b38a684e823a257b3d5c4c2d7c34bfcb937fe5658c77247b28bc90c6af,0x00852cf32173a9b3a8a2316bbe6ba0b98efcc41247a17a8aead02ccc7cb90870daccd10a44e9385abf0d0ae175fa03c0facab1d2069b79795f36d10ce25430676805,0x0174e20e49d5970117cdfc61c0a0ae062519c0c4d577f42e0d3f1cd443732b8e62deb34922a4a6d85b8b7f6df61dadffec95c17babbfaf5c57598033be0b1a44e32f,0x00a4b42ad90c0e3f7e342d8d661b4d5162ab7928b4938ab660b2e6fea3213c5d4b420123f65141a8eb7b4a46173bfce6ea1577df94f6f934f72d459c4dd3c0ef038e,0x003316c4b6c5c6b3ab3eee7f1ff365cce6045fdc43d4e6c64efa7789f2626676b47b488e6612d291d60d4a788ddd2e8b1aa8bfff02e105a285532a20ac08fa1088e7,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/curves.xml b/src/cz/crcs/ectester/data/composite/curves.xml
index e940efe..f77159c 100644
--- a/src/cz/crcs/ectester/data/composite/curves.xml
+++ b/src/cz/crcs/ectester/data/composite/curves.xml
@@ -2,45 +2,520 @@
<curves xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../schema.xsd">
<curve>
- <id>composite128</id>
+ <id>whole/composite128</id>
<bits>128</bits>
<field>prime</field>
<file>composite128.csv</file>
+ <desc>r = order = 0x03 * 0x05 * 0x3b * 0x3a107e02cd073c8e24bf55730f1733</desc>
</curve>
<curve>
- <id>composite160</id>
+ <id>whole/composite160</id>
<bits>160</bits>
<field>prime</field>
<file>composite160.csv</file>
+ <desc>r = order = 0x02 * 0x03 * 0x6b * 0x1ee99b75143833bbc11d409601c25f9566a001</desc>
</curve>
<curve>
- <id>composite192</id>
+ <id>whole/composite192</id>
<bits>192</bits>
<field>prime</field>
<file>composite192.csv</file>
+ <desc>r = order = 0x02 * 0x03 * 0x05 * 0x13 * 0x19bc3c00e2a7ad9e40d12e5d9e29a2b5ce80b3a3e84295</desc>
</curve>
<curve>
- <id>composite224</id>
+ <id>whole/composite224</id>
<bits>224</bits>
<field>prime</field>
<file>composite224.csv</file>
+ <desc>r = order = 0x02 * 0x03 * 0x1d * 0x1538e6a6dc906d724a7bf51c77bce9d46865bd92d8bca01f887405</desc>
</curve>
<curve>
- <id>composite256</id>
+ <id>whole/composite256</id>
<bits>256</bits>
<field>prime</field>
<file>composite256.csv</file>
+ <desc>r = order = 0x02 * 0x05 * 0x11 * 0x1382cadcdd2b90b90b81eda82433bf574b5d8f5654dcc62341c7e967f2e811</desc>
</curve>
<curve>
- <id>composite384</id>
+ <id>whole/composite384</id>
<bits>384</bits>
<field>prime</field>
<file>composite384.csv</file>
+ <desc>r = order = 0x05 * 0x0b * 0x3d * 0xb16aa7dc50145337cf1b2f38018ccb5cf44c22a2f7d7c22bbe5c572d2cb9a04cb1081357c6a1c97cc39ab62596867</desc>
</curve>
<curve>
- <id>composite521</id>
+ <id>whole/composite521</id>
<bits>521</bits>
<field>prime</field>
<file>composite521.csv</file>
+ <desc>r = order = 0x02 * 0x05 * 0x1f * 0x4a5aac4fac3ea253b66c3e650f5173b30467f28b8e841d37ce69bb0831a5939ad3dd082b750577ec4592d4d58916c87a9b732d8ddae435c26f8f779d2467f50f</desc>
+ </curve>
+
+ <curve>
+ <id>small/composite128</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>composite128_small.csv</file>
+ <desc>r = 0x03</desc>
+ </curve>
+ <curve>
+ <id>small/composite160</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>composite160_small.csv</file>
+ <desc>r = 0x03</desc>
+ </curve>
+ <curve>
+ <id>small/composite192</id>
+ <bits>192</bits>
+ <field>prime</field>
+ <file>composite192_small.csv</file>
+ <desc>r = 0x03</desc>
+ </curve>
+ <curve>
+ <id>small/composite224</id>
+ <bits>224</bits>
+ <field>prime</field>
+ <file>composite224_small.csv</file>
+ <desc>r = 0x03</desc>
+ </curve>
+ <curve>
+ <id>small/composite256</id>
+ <bits>256</bits>
+ <field>prime</field>
+ <file>composite256_small.csv</file>
+ <desc>r = 0x05</desc>
+ </curve>
+ <curve>
+ <id>small/composite384</id>
+ <bits>384</bits>
+ <field>prime</field>
+ <file>composite384_small.csv</file>
+ <desc>r = 0x05</desc>
+ </curve>
+ <curve>
+ <id>small/composite521</id>
+ <bits>521</bits>
+ <field>prime</field>
+ <file>composite521_small.csv</file>
+ <desc>r = 0x05</desc>
+ </curve>
+
+ <curve>
+ <id>pq/composite128</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>composite128_pq.csv</file>
+ <desc>r = 0x03f76917eb * 0x3c1be1d1dd7edf84b8013495</desc>
+ </curve>
+ <curve>
+ <id>pq/composite128/1</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>composite128_pq1.csv</file>
+ <desc>r = 0x03f76917eb</desc>
+ </curve>
+ <curve>
+ <id>pq/composite128/2</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>composite128_pq2.csv</file>
+ <desc>r = 0x3c1be1d1dd7edf84b8013495</desc>
+ </curve>
+
+ <curve>
+ <id>rg0/composite128</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>composite128_rg0.csv</file>
+ <desc>|G| divides r(so [r]G = infinity), but r != |G| = 0x03f76917eb</desc>
+ </curve>
+
+ <curve>
+ <id>pq/composite160</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>composite160_pq.csv</file>
+ <desc>r = 0x0af2407f270b81f45f * 0x4d7041e1dbf10b42f48c4f</desc>
+ </curve>
+ <curve>
+ <id>pq/composite160/1</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>composite160_pq1.csv</file>
+ <desc>r = 0x0af2407f270b81f45f</desc>
+ </curve>
+ <curve>
+ <id>pq/composite160/2</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>composite160_pq2.csv</file>
+ <desc>r = 0x4d7041e1dbf10b42f48c4f</desc>
+ </curve>
+
+ <curve>
+ <id>rg0/composite160</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>composite160_rg0.csv</file>
+ <desc>|G| divides r(so [r]G = infinity), but r != |G| = 0x0af2407f270b81f45f</desc>
+ </curve>
+
+ <curve>
+ <id>pq/composite192</id>
+ <bits>192</bits>
+ <field>prime</field>
+ <file>composite192_pq.csv</file>
+ <desc>r = 0x302b72431ff070e7e06799 * 0x35efd8bad55038e6bd22db8b805</desc>
+ </curve>
+ <curve>
+ <id>pq/composite192/1</id>
+ <bits>192</bits>
+ <field>prime</field>
+ <file>composite192_pq1.csv</file>
+ <desc>r = 0x302b72431ff070e7e06799</desc>
+ </curve>
+ <curve>
+ <id>pq/composite192/2</id>
+ <bits>192</bits>
+ <field>prime</field>
+ <file>composite192_pq2.csv</file>
+ <desc>r = 0x35efd8bad55038e6bd22db8b805</desc>
+ </curve>
+
+ <curve>
+ <id>rg0/composite192</id>
+ <bits>192</bits>
+ <field>prime</field>
+ <file>composite192_rg0.csv</file>
+ <desc>|G| divides r(so [r]G = infinity), but r != |G| = 0x302b72431ff070e7e06799</desc>
+ </curve>
+
+ <curve>
+ <id>pq/composite224</id>
+ <bits>224</bits>
+ <field>prime</field>
+ <file>composite224_pq.csv</file>
+ <desc>r = 0x1824ec370e405bfb5024db * 0x6a99de2a928e8f227e7a2ed33a555f24ef5</desc>
+ </curve>
+ <curve>
+ <id>pq/composite224/1</id>
+ <bits>224</bits>
+ <field>prime</field>
+ <file>composite224_pq1.csv</file>
+ <desc>r = 0x1824ec370e405bfb5024db</desc>
+ </curve>
+ <curve>
+ <id>pq/composite224/2</id>
+ <bits>224</bits>
+ <field>prime</field>
+ <file>composite224_pq2.csv</file>
+ <desc>r = 0x6a99de2a928e8f227e7a2ed33a555f24ef5</desc>
+ </curve>
+
+ <curve>
+ <id>rg0/composite224</id>
+ <bits>224</bits>
+ <field>prime</field>
+ <file>composite224_rg0.csv</file>
+ <desc>|G| divides r(so [r]G = infinity), but r != |G| = 0x1824ec370e405bfb5024db</desc>
+ </curve>
+
+ <curve>
+ <id>pq/composite256</id>
+ <bits>256</bits>
+ <field>prime</field>
+ <file>composite256_pq.csv</file>
+ <desc>r = 0x743bc7ea193d40db * 0x220d23234534b240aac0efa70a3bc44e046c2431ad5a32d27</desc>
+ </curve>
+ <curve>
+ <id>pq/composite256/1</id>
+ <bits>256</bits>
+ <field>prime</field>
+ <file>composite256_pq1.csv</file>
+ <desc>r = 0x743bc7ea193d40db</desc>
+ </curve>
+ <curve>
+ <id>pq/composite256/2</id>
+ <bits>256</bits>
+ <field>prime</field>
+ <file>composite256_pq2.csv</file>
+ <desc>r = 0x220d23234534b240aac0efa70a3bc44e046c2431ad5a32d27</desc>
+ </curve>
+
+ <curve>
+ <id>rg0/composite256</id>
+ <bits>256</bits>
+ <field>prime</field>
+ <file>composite256_rg0.csv</file>
+ <desc>|G| divides r(so [r]G = infinity), but r != |G| = 0x743bc7ea193d40db</desc>
+ </curve>
+
+ <curve>
+ <id>pp/carmichael128</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>carmichael_128.csv</file>
+ <desc>r = Carmichael pseudoprime = 0x2ddbfe0f1f7 * 0x5bb7fc1e3ed * 0x8993fa2d5e3</desc>
+ </curve>
+ <curve>
+ <id>pp/carmichael192</id>
+ <bits>192</bits>
+ <field>prime</field>
+ <file>carmichael_192.csv</file>
+ <desc>r = Carmichael pseudoprime = 0x730ea70deea47eeb * 0xe61d4e1bdd48fdd5 * 0x1592bf529cbed7cbf</desc>
+ </curve>
+ <curve>
+ <id>pp/carmichael224</id>
+ <bits>224</bits>
+ <field>prime</field>
+ <file>carmichael_224.csv</file>
+ <desc>r = Carmichael pseudoprime = 0x2e6e4205e9ea74ebefd * 0x5cdc840bd3d4e9d7df9 * 0x8b4ac611bdbf5ec3cf5</desc>
+ </curve>
+ <curve>
+ <id>pp/carmichael256</id>
+ <bits>256</bits>
+ <field>prime</field>
+ <file>carmichael_256.csv</file>
+ <desc>r = Carmichael pseudoprime = 0x129e94800bf86bd2d04ce1 * 0x253d290017f0d7a5a099c1 * 0x37dbbd8023e9437870e6a1</desc>
+ </curve>
+ <curve>
+ <id>pp/carmichael384</id>
+ <bits>384</bits>
+ <field>prime</field>
+ <file>carmichael_384.csv</file>
+ <desc>r = Carmichael pseudoprime = 0x78b4fa97e97300a5c46b32fb522cf76f * 0xf169f52fd2e6014b88d665f6a459eedd * 0x16a1eefc7bc5901f14d4198f1f686e64b</desc>
+ </curve>
+ <curve>
+ <id>pp/carmichael512</id>
+ <bits>512</bits>
+ <field>prime</field>
+ <file>carmichael_512.csv</file>
+ <desc>r = Carmichael pseudoprime = 0x2f6e41969c169b4e97b0a1c46ca4fb3a8f294afaefb * 0x5edc832d382d369d2f614388d949f6751e5295f5df5 * 0x8e4ac4c3d443d1ebc711e54d45eef1afad7be0f0cef</desc>
+ </curve>
+ <curve>
+ <id>pp/carmichael521</id>
+ <bits>521</bits>
+ <field>prime</field>
+ <file>carmichael_521.csv</file>
+ <desc>r = Carmichael pseudoprime = 0x170ac4fd154250e674f9ac6e0c29a214c6d6553e4f11 * 0x2e1589fa2a84a1cce9f358dc185344298dacaa7c9e21 * 0x45204ef73fc6f2b35eed054a247ce63e5482ffbaed31</desc>
+ </curve>
+
+ <curve>
+ <id>varying/160/1</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/2a.csv</file>
+ <desc>r = 2 bit prime = 2</desc>
+ </curve>
+ <curve>
+ <id>varying/160/2</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/2b.csv</file>
+ <desc>r = 2 bit prime = 3</desc>
+ </curve>
+ <curve>
+ <id>varying/160/3</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/3.csv</file>
+ <desc>r = 3 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/4</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/4.csv</file>
+ <desc>r = 4 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/5</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/5.csv</file>
+ <desc>r = 5 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/6</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/6.csv</file>
+ <desc>r = 6 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/7</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/7.csv</file>
+ <desc>r = 7 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/8</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/8.csv</file>
+ <desc>r = 8 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/10</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/10.csv</file>
+ <desc>r = 10 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/12</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/12.csv</file>
+ <desc>r = 12 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/14</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/14.csv</file>
+ <desc>r = 14 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/16</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/16.csv</file>
+ <desc>r = 16 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/20</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/20.csv</file>
+ <desc>r = 20 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/25</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/25.csv</file>
+ <desc>r = 25 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/32</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/32.csv</file>
+ <desc>r = 32 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/48</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/48.csv</file>
+ <desc>r = 48 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/64</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/64.csv</file>
+ <desc>r = 64 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/70</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/70.csv</file>
+ <desc>r = 70 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/80</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/80.csv</file>
+ <desc>r = 80 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/90</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/90.csv</file>
+ <desc>r = 90 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/96</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/96.csv</file>
+ <desc>r = 96 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/112</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/112.csv</file>
+ <desc>r = 112 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/128</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/128.csv</file>
+ <desc>r = 128 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/135</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/135.csv</file>
+ <desc>r = 135 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/140</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/140.csv</file>
+ <desc>r = 140 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/144</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/144.csv</file>
+ <desc>r = 144 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/146</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/146.csv</file>
+ <desc>r = 146 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/148</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/148.csv</file>
+ <desc>r = 148 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/150</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/150.csv</file>
+ <desc>r = 150 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/152</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/152.csv</file>
+ <desc>r = 152 bit prime</desc>
+ </curve>
+ <curve>
+ <id>varying/160/152cofactor</id>
+ <bits>160</bits>
+ <field>prime</field>
+ <file>varying/160/152_cofactor.csv</file>
+ <desc>r = 152 bit prime, with correct cofactor</desc>
</curve>
</curves> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/keys.xml b/src/cz/crcs/ectester/data/composite/keys.xml
index f333042..8a98135 100644
--- a/src/cz/crcs/ectester/data/composite/keys.xml
+++ b/src/cz/crcs/ectester/data/composite/keys.xml
@@ -2,569 +2,569 @@
<keys xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../schema.xsd"
category="composite"
- desc="Points on the non-prime curves, very small point orders(3-5).">
+ desc="Points on the composite curves, very small point orders(3-5).">
<pubkey>
<id>composite128/1</id>
<inline>0x746fa441b3a54d3c531bd59d119f400d,0x73aff68dbd96e1485cd2de0f6389cc70</inline>
- <curve>composite/composite128</curve>
+ <curve>composite/whole/composite128</curve>
<desc>order = 3</desc>
</pubkey>
<pubkey>
<id>composite128/2</id>
<inline>0x6e9dc37af66af0045d7a2e414d4bfb89,0x40b01d2f36c9a5b2a1cb28386dd12470</inline>
- <curve>composite/composite128</curve>
+ <curve>composite/whole/composite128</curve>
<desc>order = 5</desc>
</pubkey>
<pubkey>
<id>composite128/3</id>
<inline>0x32076e371a48d82777ce851969439ab8,0xb049b7d6ba6f2d9c6ce240bc689d3556</inline>
- <curve>composite/composite128</curve>
+ <curve>composite/whole/composite128</curve>
<desc>order = 15</desc>
</pubkey>
<pubkey>
<id>composite128/4</id>
<inline>0xc819a68e95796650cd7d11e8ad65806f,0x280e9c9b7e5d9a5e07653ee2afac83e7</inline>
- <curve>composite/composite128</curve>
+ <curve>composite/whole/composite128</curve>
<desc>order = 59</desc>
</pubkey>
<pubkey>
<id>composite128/5</id>
<inline>0x66f66346d87e2214bf1bfc3331628c81,0x8c1a74b09bbbb515b027d89dcc1cecb2</inline>
- <curve>composite/composite128</curve>
+ <curve>composite/whole/composite128</curve>
<desc>order = 177</desc>
</pubkey>
<pubkey>
<id>composite128/6</id>
<inline>0xa546a97bd17378bd6e5c42c4ab857cac,0x13b99be68904a968a8d4ca6feab23f40</inline>
- <curve>composite/composite128</curve>
+ <curve>composite/whole/composite128</curve>
<desc>order = 295</desc>
</pubkey>
<pubkey>
<id>composite128/7</id>
<inline>0x6ae9f873a9da27b41e676d3514c96e56,0x8f6479493be1835cee6b9f29df21f74f</inline>
- <curve>composite/composite128</curve>
+ <curve>composite/whole/composite128</curve>
<desc>order = 885</desc>
</pubkey>
<pubkey>
<id>composite160/1</id>
<inline>0x37efeffb592df52c0080de1a5074505fb9bd7d6f,0x0000000000000000000000000000000000000000</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 2</desc>
</pubkey>
<pubkey>
<id>composite160/2</id>
<inline>0x68684425389f5552a24b7c205e19da7a0c10a1cb,0x825ecf13c08f314cd6ad5eae73044c71e9876409</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 3</desc>
</pubkey>
<pubkey>
<id>composite160/3</id>
<inline>0x61602e67d8e17442afb37c07ea9fff2beb6c5b63,0x525e64d325c225855df22c141ab48292e2f8f937</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 4</desc>
</pubkey>
<pubkey>
<id>composite160/4</id>
<inline>0x041fea694918a16ede5e6c32e24f52f7827b7942,0x0c4005ad4b02d3f04ba662cca7c5ae4de9a9ba1e</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 6</desc>
</pubkey>
<pubkey>
<id>composite160/5</id>
<inline>0x896db2058ec6de5bf0c3d4729449c161f3a6513c,0x168828b2d35afa6ae22cfb88470444ecfe31565a</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 12</desc>
</pubkey>
<pubkey>
<id>composite160/6</id>
<inline>0x5addb1c0c2b73b1c3bfa6ee1d4fa55c3d6cb79c8,0x18cf3b6fc6ac06a6af69817234799a7bed594e16</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 107</desc>
</pubkey>
<pubkey>
<id>composite160/7</id>
<inline>0x2a8b120fa9fb0901280068fac4c7343c91707974,0x3c64f73118aa3e6263f988428d4f8e931c835dbd</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 214</desc>
</pubkey>
<pubkey>
<id>composite160/8</id>
<inline>0x09814e9b98b521aa510d24e2eb68484f9cd4f446,0x030f959368478d906bd830105e1e645f9a3e7aa7</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 321</desc>
</pubkey>
<pubkey>
<id>composite160/9</id>
<inline>0x475d0927fdea77619a4c0f3d7f78fa17b1a82ebf,0x0f9ef6e4b67034f84f2568cf93bcd6244f99befb</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 428</desc>
</pubkey>
<pubkey>
<id>composite160/10</id>
<inline>0x441a137ed2bbe1397492bacec4d8d98e54e88fcd,0x1ba3217b753b1fd483ebd0eb6ce6642ab8f9b1d1</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 642</desc>
</pubkey>
<pubkey>
<id>composite160/11</id>
<inline>0x8fcb8221093a80fe3ab7ee7ce952ae78e21177c3,0x29c944efc6e04c8a3393470be6eff62e250795c8</inline>
- <curve>composite/composite160</curve>
+ <curve>composite/whole/composite160</curve>
<desc>order = 504</desc>
</pubkey>
<pubkey>
<id>composite192/1</id>
<inline>0x8220bcea81992c46bc57e0dae661eeff29e66d64b33253c5,0x000000000000000000000000000000000000000000000000</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 2</desc>
</pubkey>
<pubkey>
<id>composite192/2</id>
<inline>0x94863540fdd9e8f415df79e18aee4bdd0914127581b6bb15,0x3aa760e488d12f8f93b10da531e1dbc033db25729119839f</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 3</desc>
</pubkey>
<pubkey>
<id>composite192/3</id>
<inline>0x0cdf12ec0389daa5dc4fb9a877082e7acc4d7054d7eb320d,0x2a135f63802b9bb9064ffe6d319942ada312b0a06a506c68</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 5</desc>
</pubkey>
<pubkey>
<id>composite192/4</id>
<inline>0x3d2cf1aa8ef6db0076b8e026f5f5eeb612bed45c2bf57796,0x40b1b1c78925a90c4f9c994ee9ac8a97ce8e1e5613676ec1</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 6</desc>
</pubkey>
<pubkey>
<id>composite192/5</id>
<inline>0x069f245ec322d6ed422f18b4df1b2728bcff22a08c160de7,0x792466cd587549a3ffb4dbe491d54e5df25494ba9be83472</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 9</desc>
</pubkey>
<pubkey>
<id>composite192/6</id>
<inline>0x649ddaeba68589618a326232704a4324957c8191fd558c60,0x9461496a59b680b82f199144c29323e061273efa62a60faf</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 10</desc>
</pubkey>
<pubkey>
<id>composite192/7</id>
<inline>0x319a75780c9090f769b69b082ad16dbce0e8bdbc16d04cd5,0x76b03040b524f21b3dd5008995459ca8ed35dae3722c7035</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 15</desc>
</pubkey>
<pubkey>
<id>composite192/8</id>
<inline>0x77acef779d8562b4492309adf946f5970bb83190ad76a2e3,0x3e98d9c7b72a8bfd5c6f6a7c07478df003d273b1326caa6c</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 18</desc>
</pubkey>
<pubkey>
<id>composite192/9</id>
<inline>0x1e90f09d5328536457f6d9fe58444f086e32229007ef12fc,0x26407fbfba9f796afa97ea2c2e986d3343d711015b220f44</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 19</desc>
</pubkey>
<pubkey>
<id>composite192/10</id>
<inline>0xa2e5982912dd423cfb745a01088e540b41e19ba84107cddc,0xaa29fc9dd974238b9daf73997d3c4dd331584d87356f9549</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 30</desc>
</pubkey>
<pubkey>
<id>composite192/11</id>
<inline>0x670c2e74df1cf4f473ab37ef685b2a915858863bc9c67868,0x2edc6b47a9fbe500c2f4f4b79bb44b229dd99194aca26d5a</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 38</desc>
</pubkey>
<pubkey>
<id>composite192/12</id>
<inline>0x14c936965c39188192d431aaf96f37e0d398b5a858933b3c,0x19c6526df20625d92445007603f19dd120702351869f9ae3</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 45</desc>
</pubkey>
<pubkey>
<id>composite192/13</id>
<inline>0x595694d6d70b13b372b2f1b4daf5ffd391513d9542b0d600,0x099f0ac0ce38d9920f3c59a63433230f4f945716c8d246f9</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 57</desc>
</pubkey>
<pubkey>
<id>composite192/14</id>
<inline>0x09cf293ad9517ef1932fb81a4800d60a768356fd2980ae77,0x1b12ab568cb4ac07593bb7cd6bc8a9364bac3c345419026f</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 90</desc>
</pubkey>
<pubkey>
<id>composite192/15</id>
<inline>0x9424bf6ba15758fc88df622be2a7055ebd34bb0e8e89c945,0x2611aaf3752880c39238f669d910ca591358e5aa06f95119</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 95</desc>
</pubkey>
<pubkey>
<id>composite192/16</id>
<inline>0x4289f802fa238ded56eda2164532f205cdde5b9ba58b8226,0xa2e1cdff2ae8312f4882ff44e4ef1d9e16be424fecd624e3</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 114</desc>
</pubkey>
<pubkey>
<id>composite192/17</id>
<inline>0x5cabb4f80e166127067104af1327a8531c053ec510702d6a,0x2fdd3945ffdde5e5389ff43ec323031f9c39b795fbb9f41b</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 171</desc>
</pubkey>
<pubkey>
<id>composite192/18</id>
<inline>0x9a6f5c897b695025e86d74043bf6a5a2bdf38ea7e2fe8f0e,0x4367779cadb1f8a193ac73dc51293aa0e94e930456e89692</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 190</desc>
</pubkey>
<pubkey>
<id>composite192/19</id>
<inline>0x30f786b7a6a3292c40a1a2ac6934646595787c4f003a08c3,0x84e4b9970c123d1f5188fca8f27152d377d85f2352543992</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 285</desc>
</pubkey>
<pubkey>
<id>composite192/20</id>
<inline>0x042d015cd6633de4ed1700c346774ae17263b3e284b43162,0x7c27c4593d37115d93bfd33797ae73f0805117b032289e46</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 342</desc>
</pubkey>
<pubkey>
<id>composite192/21</id>
<inline>0x9f62978f1018599e5139fa6560fe3a39c108674f361b1389,0x884e25851a5de235df686fbb870e6b7b81accb8bbc63cd15</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 570</desc>
</pubkey>
<pubkey>
<id>composite192/22</id>
<inline>0x29d846d8f363bc58149fdf6eaced9dbc7692a0942f6ecabb,0x784af0c66238ef9cdf900eee2fdce8081d2aa59dd327c8c3</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 855</desc>
</pubkey>
<pubkey>
<id>composite192/23</id>
<inline>0x3c6d33801293213a71f4a7d9b1091cabb89bcf7fc266084e,0x80eb1f866a3774c45811feaee8cda2f020e5aec70a2b5233</inline>
- <curve>composite/composite192</curve>
+ <curve>composite/whole/composite192</curve>
<desc>order = 1710</desc>
</pubkey>
<pubkey>
<id>composite224/1</id>
<inline>0x14f89a6ef687659649fd6e0e6cb1f7f27c0f9f94fc872e7f54a9c856,0x00000000000000000000000000000000000000000000000000000000</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 2</desc>
</pubkey>
<pubkey>
<id>composite224/2</id>
<inline>0xb4fbabc7cf96b62b08edbaa2df53346bbb871c121bbb35e771c74db5,0x61cf8b556f068f45ec69963964a0e8ab72c1fa0be48e2ea886235956</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 3</desc>
</pubkey>
<pubkey>
<id>composite224/3</id>
<inline>0x5b98ef6f104d0cc4159cc793d52713bafbc2b37a9f64af8f962b1c5a,0x7935aef16b1cb800beca9ab322aa8ecf8281f870057a8e1fbdd72490</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 4</desc>
</pubkey>
<pubkey>
<id>composite224/4</id>
<inline>0x3abe85a7ef34758c487373eb1f193a86f2b073b23a42ab3753596308,0xca9743c8ebf2fe6ceb300b93e0742ebe5f594b2ed84dba7f42f7aedc</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 6</desc>
</pubkey>
<pubkey>
<id>composite224/5</id>
<inline>0x3b931bbe008a038b5a5b03cf34c4102ba919579bd0a81f066193ab76,0x794f623ed1525010559240ad899b19a841bbbb818a64f32fc28c9931</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 8</desc>
</pubkey>
<pubkey>
<id>composite224/6</id>
<inline>0x6ca8b206ce077be28ff56c18295508ade9fce4a051d4975d61ee84d0,0x1f5720ccc870e31e83eb58f7c7c5ada471f7502ae5b2d87a69109df7</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 12</desc>
</pubkey>
<pubkey>
<id>composite224/7</id>
<inline>0x45437959ee88358cd8ee9902139cf6c9eee124c8ee199bd1a1ecc2da,0x756ad18b140d6a13a010fc21f1c4cf45a67eeb4c3dd4b202e9ae775f</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 16</desc>
</pubkey>
<pubkey>
<id>composite224/8</id>
<inline>0xd2074198f477e79a92918d4a5bc0ba104de4b0369104a8b51012595d,0x5025127d318e3c34e4fbbefb397874a3ed50a9cfd6ca455d4be02125</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 24</desc>
</pubkey>
<pubkey>
<id>composite224/9</id>
<inline>0x4513ad86e9415caae932018d67c869dbbe001cd53e64d82d205f4e2a,0x130dbd3e71618ddb0464bf3e894c30e1dd3bc25bb01e09e5b50a001d</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 29</desc>
</pubkey>
<pubkey>
<id>composite224/10</id>
<inline>0x2f4f470b72c093667e3f433a5189988adbb0fe1ae36482c3eeecf8a4,0xc1ac6c167ff41b0842f6470bac49d2a518da6c4c456c5657be15dec6</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 32</desc>
</pubkey>
<pubkey>
<id>composite224/11</id>
<inline>0x58741bd7ac127ecf8aa7c9fd78d22d81f8c10bb971bb77c015f69cd6,0x52e914fc15edb4af4a53ebeaf8466d2b7cf1bfe4a78c036a8faa5cdf</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 48</desc>
</pubkey>
<pubkey>
<id>composite224/12</id>
<inline>0x7a06eeb07784de6a15d1322243b4edbe24eb9d24869e1d9b7b883686,0xba5f157579eda39cc85cf04cd48f710133716a0fa0f5a48c3948381c</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 58</desc>
</pubkey>
<pubkey>
<id>composite224/13</id>
<inline>0x67d78ae1eaa30a898a3497c0cff43675be6d8cd4e41971661e8622b8,0x2e7337490aa8220d721167f7d047952af1d68615b07619607c771f5d</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 87</desc>
</pubkey>
<pubkey>
<id>composite224/</id>
<inline>0x30eea9b5158e7ba9ba6a2a955942e3324c6539a70e78270abe43f7fd,0xb3eb76bbcac6cd68e28688d70f431d26147bbb380bf1938d8038418e</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 96</desc>
</pubkey>
<pubkey>
<id>composite224/14</id>
<inline>0x4a27a6d15ecdfa776161aa180a4cd2de898610aac1b274f7a85d7ef1,0xd92847404473b63060e1514fe6a431130a79512c867d89eda0e3c674</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 116</desc>
</pubkey>
<pubkey>
<id>composite224/15</id>
<inline>0x6a7ed0907ecee744da1a57ec48ff6cfc0d8d77c67a585fd9750081e6,0x96106e57beafd660a8622f6341967fd4565ce9f4f09793cc3f287316</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 174</desc>
</pubkey>
<pubkey>
<id>composite224/16</id>
<inline>0x52c53640843d85f9945b18452a96e48816bbb52c76d012b3bd197f79,0x9630aba4de01758e0aaddef1de1cfb070af629f80c3ad3bb21e3cce5</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 232</desc>
</pubkey>
<pubkey>
<id>composite224/17</id>
<inline>0x88166b34bee1151dc0589da4bed6da8c6a2e9d4c78eb4ef21c5a9efd,0xbb92af84b1faffb9cbd516316e2c58dabd3867c5ac4dccb4b3d7c25c</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 348</desc>
</pubkey>
<pubkey>
<id>composite224/18</id>
<inline>0x02edb51c0bc83b37cc89d2a7eab42719f0c847d61334022b6ca765c6,0xe08729140e552810499c414488de5751769d595940be05992e1e2977</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 464</desc>
</pubkey>
<pubkey>
<id>composite224/19</id>
<inline>0x96967cf6b0ae919e50f815ac8ebcc35d0625b518d3fd095224b3c70a,0xd7d51361df21536593163d588bb4843a3ea53bfb114e43afa5eae2fb</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 696</desc>
</pubkey>
<pubkey>
<id>composite224/20</id>
<inline>0xb2b0a8e35a9597549a98a150f2b2a311feb560c99923e5ad23befcfa,0x6275928b50ccfd639b81c77c65a8d016c7ea4a035975e871dd10ef5d</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 928</desc>
</pubkey>
<pubkey>
<id>composite224/21</id>
<inline>0xd22b61d5ba5ee04d963bedcbb11165c23990b7053e5d9aef656eb078,0xa000d64563591df0b2f9e270247bca57b242e70f58ed57b4a8acec2e</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 1392</desc>
</pubkey>
<pubkey>
<id>composite224/22</id>
<inline>0x1f126f0463995cd293799fc58cb3efa1459a539cbd2d88c8d7283cfc,0x51175df02b5884fce8bfd17a7a97ccf12a5fdfdec4c297b301e477cc</inline>
- <curve>composite/composite224</curve>
+ <curve>composite/whole/composite224</curve>
<desc>order = 2784</desc>
</pubkey>
<pubkey>
<id>composite256/1</id>
<inline>0xadd83091be650ca4d78b81c1ae2851a9197a5fe33a136d368ecbb1fe06200764,0x0000000000000000000000000000000000000000000000000000000000000000</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 2</desc>
</pubkey>
<pubkey>
<id>composite256/2</id>
<inline>0x8ca20dd1fa045339a171513fb1daa25fa7439e4b97c129c6039e4b9abbac1532,0xb565bde8fe9831f0bce07d70784dc1b7064c443b54b5e96408c1942e30437cc3</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 5</desc>
</pubkey>
<pubkey>
<id>composite256/3</id>
<inline>0x7f25698dc1a9a0810dbd97e1918ea4a78f20783ce3ed4133df0fe6f66fe29c3f,0x0eff3a76e05d5e24b6b57c13f704ea2a54750502000c9d3f04d1ad932cfb6d3e</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 10</desc>
</pubkey>
<pubkey>
<id>composite256/4</id>
<inline>0x8b6be31db337293200eb7a6a2ac144374223a4f76ea7b003eb789d0622cbc806,0xd9556692a39eb79d29c0a019d94f88737edd90006f55ecdc1ac204c81eb0c32b</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 17</desc>
</pubkey>
<pubkey>
<id>composite256/5</id>
<inline>0x497170999460d32516062fa49929789e645a46e2db216e83a7f738d2c5c482d6,0xa1666de87f4f0de0ed523a962d386349d87b4e40c7c6db555e52e33da3de738b</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 34</desc>
</pubkey>
<pubkey>
<id>composite256/6</id>
<inline>0x409a4d05651cfa87af444fa58f9d3fa3d5bbd25a8c9f7a6be200b5255bb06bac,0x3a08b088284a3da5c59246379b9b7aa36a86917f58c390cc49d2172e33d5c094</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 85</desc>
</pubkey>
<pubkey>
<id>composite256/7</id>
<inline>0x5ebd412e2785d08f2fd0403a3df2d028a4c33c887637d75ce05543cb6c33f172,0xa3f76e00200df483e710db5724c08ef01f813959ae3205b5e4e3c7a051d303b8</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 170</desc>
</pubkey>
<pubkey>
<id>composite256/8</id>
<inline>0x756ab6f97c43c68c38c8070766c3d86df422f8bc9c8e5ff8e8fee0af683b58e0,0x08746e1b87c5e8e582fa8a4e13b5971728af1e6c6f74a28478b0a606357c17b4</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 289</desc>
</pubkey>
<pubkey>
<id>composite256/9</id>
<inline>0x0e02b7a9def8eb46986ad908a49109267beb19e331bc399eb036ec087c2081c5,0xa1e1fff1a84a3b131c072f76c1ed54293f5d82dc5c9c78c9984786648d172cb2</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 578</desc>
</pubkey>
<pubkey>
<id>composite256/10</id>
<inline>0x5330e8ad3035f2b256091a362313ae5b7f183d11c3fce1528443cf2626911e09,0xb3abb61c1ac189a3980f8c6dfc4330997096dca089273000a7302682b40ff6bc</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 1445</desc>
</pubkey>
<pubkey>
<id>composite256/11</id>
<inline>0x31f4f374d564ec73cd4e066ec84cdfa89be9389c2c0e557d0226af8f4a960768,0xba1b2169c90ea6cf612db29e4142c1483f9268012114148e28d35969669a7549</inline>
- <curve>composite/composite256</curve>
+ <curve>composite/whole/composite256</curve>
<desc>order = 2890</desc>
</pubkey>
<pubkey>
<id>composite384/1</id>
<inline>0x5136c182f03241ec87e6eec1728c1fb2d6b2ddcd4d9abf2a110c337419c4ec7cc8386b7b9ea9f5cb18b0f3c2a78e6489,0x9130cb73f8064fddb24d8c6a216b57fe99df93bcc82c93343617a5246ca1643fe57a06d6112a1791d1bd3643fbd9c041</inline>
- <curve>composite/composite384</curve>
+ <curve>composite/whole/composite384</curve>
<desc>order = 5</desc>
</pubkey>
<pubkey>
<id>composite384/2</id>
<inline>0x20070cc3e17bf1c770ef297b679c54d6454a3cd5effd94e236677b10e3e8075a8a9902ecd71e930f19fda4d79931502d,0x04a21190dbba4b6efe62640887256163ba5c9fa706aad74f1bfebdc27ca6f9e2f9b37bf9abf2c72803968799e2c7e702</inline>
- <curve>composite/composite384</curve>
+ <curve>composite/whole/composite384</curve>
<desc>order = 11</desc>
</pubkey>
<pubkey>
<id>composite384/3</id>
<inline>0x6d24691bacf187946f24885f2bec9a6b09239f4b7d93651c8c62f0221ba695baa5f70c49028ca5bc462289edcec081fe,0x7489fb2fd719c84ab0a12eed6f5f45fabb7c19d49d9d185a4d4efcffc9d2110a1b5a04961251f1ab19908662c8dadc9a</inline>
- <curve>composite/composite384</curve>
+ <curve>composite/whole/composite384</curve>
<desc>order = 55</desc>
</pubkey>
<pubkey>
<id>composite384/4</id>
<inline>0x0c5dccdb9c83f4d3cad69213b80f2c969210a228b85dce49c8a31ad08cf232118c6eb03d3b7e3d7bc8add230c24d184b,0x6316b45ee6832912cf3d54fc1fb73de47753ed225074cf76ebcdecb5f0c797e166b90767e2f267a4ea6b43cf6cde23c1</inline>
- <curve>composite/composite384</curve>
+ <curve>composite/whole/composite384</curve>
<desc>order = 61</desc>
</pubkey>
<pubkey>
<id>composite384/5</id>
<inline>0x32a43b215a94626d6f28974d5622469ebbdb7a54fef268267066fa3199f343f044248f39bf6ef10bdfffa6cb80155bb7,0x3d6a14e4bfec02b2306649a6da4fbbac157cecb3faa6cc9e62b5a469ea7f17a6f5e66a7c6753eee3f9cb7bdd4d0f8a4c</inline>
- <curve>composite/composite384</curve>
+ <curve>composite/whole/composite384</curve>
<desc>order = 305</desc>
</pubkey>
<pubkey>
<id>composite384/6</id>
<inline>0x5baac92f9d31ffd1cf982566f6d4bc239350ffae1f6b068ec07fb200795f4a902978d080a70d5908bd8ee283723ee196,0x164584fff8bb749bb781eedc62f9a39f658490969d24bff24b5c91f7af7eb7dd967b0066daf54678788f241b67d1a78b</inline>
- <curve>composite/composite384</curve>
+ <curve>composite/whole/composite384</curve>
<desc>order = 671</desc>
</pubkey>
<pubkey>
<id>composite384/7</id>
<inline>0x3b2d81fd9001d4b208e9d6312553bc3c2ca0853145dd882188b4b197152faca8f1194826c745f74c90d96594dcc0794b,0x8fef63c95e804b6ab0bbe7142bb56ecaa24737e8f97466d68f0c9ca7c230480b28d958d69277fcbcd77f6a566423ddec</inline>
- <curve>composite/composite384</curve>
+ <curve>composite/whole/composite384</curve>
<desc>order = 3355</desc>
</pubkey>
<pubkey>
<id>composite521/1</id>
<inline>0x01221fb007e1c2f7413b4d79a0265baf9d9ea2850e9e262b28ef5ead6f5f505d05cf731a891a443e7c1a35c867d7a3de4118f76d1cb68f6479eb85fe87fc9c6be098,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 2</desc>
</pubkey>
<pubkey>
<id>composite521/2</id>
<inline>0x00a4b42ad90c0e3f7e342d8d661b4d5162ab7928b4938ab660b2e6fea3213c5d4b420123f65141a8eb7b4a46173bfce6ea1577df94f6f934f72d459c4dd3c0ef038e,0x003316c4b6c5c6b3ab3eee7f1ff365cce6045fdc43d4e6c64efa7789f2626676b47b488e6612d291d60d4a788ddd2e8b1aa8bfff02e105a285532a20ac08fa1088e7</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 5</desc>
</pubkey>
<pubkey>
<id>composite521/3</id>
<inline>0x0039ccb35a071951bda5c9c40edb1fbfa365ce59a2a89ee37739708d748cc66bb19cbcfa30cc4ef6bfbb48728e930d940e30c64b6d77c0e64c79c1bad49540084662,0x00d7016bd5016c8ba9601ec3dd44f77b8ff7bb3aaa6c358ac78bf931f7f4d140e4de1912c343bfe7956ab0b29aa9ec0922008d025e9895a8141bd7c88f913e745e29</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 10</desc>
</pubkey>
<pubkey>
<id>composite521/4</id>
<inline>0x00426f8691e7f8afc0f7443206d3d44779b96c942714386733853530d3af4944e1ad38c7c1047f50e2bf8db7dfc0d4a8803976da934eaaa19e478ee026736ae8ac6d,0x00c97e0d2dedcd7b601430f1b8959c26c24918f6c9bd803bfe8cc015e7285956f878f27a33c91f64fec051f478cadcb7ed80c21127a7916d1e2c88ee921f1f65cf94</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 25</desc>
</pubkey>
<pubkey>
<id>composite521/5</id>
<inline>0x001550be76b460f82f2fbf3ebfd9709c50c07ec18c250c01b7d934eda2bcf3b78f648b7dd813cfd58a3f12ab35ad015c03ed0e14af6ef1560706dd59fafc32ecd5aa,0x00eb5368f5c53f70d88bbb1f31afe0d730aac4523b998043b2029a441528f7ae3483773117184e8d2efc875fe5447b0eb4ffb781bb014c67505434477fc4d6e343cd</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 31</desc>
</pubkey>
<pubkey>
<id>composite521/6</id>
<inline>0x016bad260ce10570e179138810152059e4ed8d1a6f5d8f8f2697ff98e8a1d8400cb5fb2334e5ccd88c3933add314e1f94b67ce99a4594da7754b39d58262c2275827,0x004a9b47353f119a01bb8dff6f63b58499a83c20a6fb8cbf84e717e35643c23eefef157891ca720b332355b70ee265bad5e057958ee42ab6a0f0675aa85caaad4a8d</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 50</desc>
</pubkey>
<pubkey>
<id>composite521/7</id>
<inline>0x01320c8762348be979ddf729b42a3839bd8e6a99923b3bab663dbb298f470d0e3aac375a1d1aa7119ec5b2e82c7921f192bea4ac81b7259af3a417135e82ad56aa4b,0x01c0be727f0480ea5137efc3fd201fca223ecd58d34dcc31cbfd6b7909b3033bb7d65e006e4dfe7c80f2a75d0bb5256986077d16cdd3c4d74bddfedc700c5be39541</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 62</desc>
</pubkey>
<pubkey>
<id>composite521/8</id>
<inline>0x0097c707694d550fe1533a9ce461e0317206385ee961cc3c646cbe84afc17a426023c8dd1e8db9df81bfd01b8cd123fd381c7fffd375f1776eb69994c94d67088ddc,0x00f3c16b5bb57044a555c5c89dc0fe1d2dec3406a645e66811d9a466a687884133cb9863394ddb19e2888d1f311d88060b0601f960d8a2ba86f67b4e1c8dad61326b</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 155</desc>
</pubkey>
<pubkey>
<id>composite521/9</id>
<inline>0x014ae6ee5a69767d8abb24d62d0435807e36d9c42572eeb2a7d2852837f68d62dd97c4ae4ed4b47f1208e9b80c0e285b69db277be2072e104b1892892be5e09d1d6a,0x0008a34156d7f671159b1bd85ab0413092fb16de8a6ea9ddae20c427262d2636b926339bf1ad1a2a1518aba13d3ce858f7b232971ebdb3b54b61e1273defd0c20ba7</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 310</desc>
</pubkey>
<pubkey>
<id>composite521/10</id>
<inline>0x00f6d940ce18d53a7706999da53c40cb8e4581a73069ae4358747257a169ab1532474b43e506603fcbd743b63b48551faa3bcac5fb1a40ca2b3f49f369fec36b7c7d,0x00f881dbc0ab0b74c20db84810eb476b1fb852398e87f8d909873f0b73cce0166baf43f07487a7a35a172000f5050c8531b108afb03c2654fa4a81b0538b58c4ddb1</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 775</desc>
</pubkey>
<pubkey>
<id>composite521/11</id>
<inline>0x0012538aae315d49a9b443382a19de468f57c7ff2494ecbaa54e927d3affb6d1d6503cb3acfbb0feee44caeb7fbef8804ac073c709a90eb3c7464a6644c9c5581e9b,0x01afeb2c9e1b519804e3a73364953368f915e6abc765adbd3ec7cfc2b808b1b4b46d575a664d06b4b455850cf295fd69eb823ca069cd2de90542db1496ad9095fad4</inline>
- <curve>composite/composite521</curve>
+ <curve>composite/whole/composite521</curve>
<desc>order = 1550</desc>
</pubkey>
</keys> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/10.csv b/src/cz/crcs/ectester/data/composite/varying/160/10.csv
new file mode 100644
index 0000000..5fa842a
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/10.csv
@@ -0,0 +1 @@
+0xb1c8eb4d314d22f1bdb2294eaed063e64f580611,0x6a1a4b89dc64200e98c46af58e8d7d0a52aba862,0xa0c9a0d9070ceefcaa3f2324668d6e3e9a3bf8f7,0x4b517e44056658e1f778d6c1075eefc644eaae5e,0x15ca498bd6ab9519c5be6f29882cbc68e47479cd,0x0000000000000000000000000000000000000337,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/112.csv b/src/cz/crcs/ectester/data/composite/varying/160/112.csv
new file mode 100644
index 0000000..633ccd5
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/112.csv
@@ -0,0 +1 @@
+0x9f3386530aa0a8009acbbe9caa919f72c8d5730f,0x33f8b03510268eb1ca33c2996ddacec1b314c5a6,0x4d9b3a2737345fe43069f306eabdc123e8e847b2,0x803f5afafe7ccb0433355eaf7a1aa1e93d1161b0,0x702c66bf3f3235fbcf3e2a7bf3bf56a69169d1c1,0x000000000000c978cb903a08ddcef1daa40de1f5,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/12.csv b/src/cz/crcs/ectester/data/composite/varying/160/12.csv
new file mode 100644
index 0000000..62bb1a0
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/12.csv
@@ -0,0 +1 @@
+0xa7d15a5258f4f3855cb22ce8d00571133e8ad0f3,0x61f9830a932a4cdd257061624f3b820e9b91db6e,0x758ee90aa5d7fe797c4817d0c2011f062a263429,0x4f448e668102ec49a2042cf2c15f9879d2d14068,0x05043866b8c4d47377f25942b075e835b121ceeb,0x0000000000000000000000000000000000000c25,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/128.csv b/src/cz/crcs/ectester/data/composite/varying/160/128.csv
new file mode 100644
index 0000000..5f8c532
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/128.csv
@@ -0,0 +1 @@
+0xb13f0d997960752db0a77c95ade4843941645c87,0x7acba0516ea114053bc3e8fa026857990e610d4b,0x7f9755351f5279758bde2b9739c5f907d159ff26,0x08010035ebd4107beb815893817f2b00f7911d96,0x932569a7385306a3b33e4669100feda47db97168,0x00000000c85d322721a790e50860fee459f6292f,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/135.csv b/src/cz/crcs/ectester/data/composite/varying/160/135.csv
new file mode 100644
index 0000000..232abff
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/135.csv
@@ -0,0 +1 @@
+0xd3f3289b14ab182f38b78fab5dbaf3674c02597d,0xb8880d01c2b44c8a27805524913e438e6458411d,0x89482f3814165014cc30b134849ead387c7ad048,0xc44043b00f6f65000cb63a22fbbb0785985d0699,0x6097e0e529330900f844ccd27a69a96b16509c16,0x0000006c7fcc23ea5ce765d52954b58745d67e81,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/14.csv b/src/cz/crcs/ectester/data/composite/varying/160/14.csv
new file mode 100644
index 0000000..c8df53e
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/14.csv
@@ -0,0 +1 @@
+0xbdf7ada7a57600f5d5b371b51218a619536cebc7,0x799707863618aaaffb5d46ca3427d6cfecdc6476,0x590f7e7193a997a2b60ab8e31107f1832473290b,0x795684e5a9816c14dff9c8b509c8c87afa3bbbc3,0xaabbea132ba2097d8025a5387aed8482147c530a,0x0000000000000000000000000000000000003437,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/140.csv b/src/cz/crcs/ectester/data/composite/varying/160/140.csv
new file mode 100644
index 0000000..4d59858
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/140.csv
@@ -0,0 +1 @@
+0xcf8ecac9bc992d2df7ba9015b5bdcbdf2d1c2aa9,0xa067f72ab472977a150f4684df8e9ccee909489f,0x080cac1702258fce0fbafbdb4f861ad4554a05c6,0xa4601066e4fcb7308022ac922a3a1475197e723e,0x0a210871677b6b921846b4ff0c055cd93f2aa275,0x00000fe55175f2c1fc9827ef4997357705b40a5d,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/144.csv b/src/cz/crcs/ectester/data/composite/varying/160/144.csv
new file mode 100644
index 0000000..e8c6492
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/144.csv
@@ -0,0 +1 @@
+0xc4bfe673203f80fd04c89a5942c18074bcc2a719,0x9d4a0edafeb576559fe95f1dfde0e006a9e0f6fb,0x2c075927ef142a14c84de72b208e8b5ee1d762b0,0x5a808971a0093ceadb15cf76068c5e7c3c4269b1,0x27a0f2741a55767ef3175461120c5f42a5b54f4f,0x0000d9935a273b9b1402519925d6a6a8b4f9342b,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/146.csv b/src/cz/crcs/ectester/data/composite/varying/160/146.csv
new file mode 100644
index 0000000..f656c72
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/146.csv
@@ -0,0 +1 @@
+0xbdf7ada7a57600f5d5b371b51218a619536cebc7,0x799707863618aaaffb5d46ca3427d6cfecdc6476,0x590f7e7193a997a2b60ab8e31107f1832473290b,0x4ccf365eda5a0e85438b6df2bf57d668cf5d8192,0x702b5f386587f0d85e6cf56b511de035b62c4379,0x0003a3606233edce56cac59bd01e622561e99e77,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/148.csv b/src/cz/crcs/ectester/data/composite/varying/160/148.csv
new file mode 100644
index 0000000..b292889
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/148.csv
@@ -0,0 +1 @@
+0xa7d15a5258f4f3855cb22ce8d00571133e8ad0f3,0x61f9830a932a4cdd257061624f3b820e9b91db6e,0x758ee90aa5d7fe797c4817d0c2011f062a263429,0x356da5d90cef81adb97a8cc3e95861fc156ab6c3,0x63ea1cb827821f6d3599e303594a4e21911971a3,0x000dd1818cc0197085816a97b6056c3917bb32d9,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/150.csv b/src/cz/crcs/ectester/data/composite/varying/160/150.csv
new file mode 100644
index 0000000..c1bf12e
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/150.csv
@@ -0,0 +1 @@
+0xb1c8eb4d314d22f1bdb2294eaed063e64f580611,0x6a1a4b89dc64200e98c46af58e8d7d0a52aba862,0xa0c9a0d9070ceefcaa3f2324668d6e3e9a3bf8f7,0x39ce0be4410100e1349fae8ec18fabb91f1816dd,0x3a44dee9ecb21038fb8c3e987e285f09b456bdc7,0x00374d1df48d00aa21837b6f9717173eb656c659,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/152.csv b/src/cz/crcs/ectester/data/composite/varying/160/152.csv
new file mode 100644
index 0000000..24a03ba
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/152.csv
@@ -0,0 +1 @@
+0xc9d72249375ff1884a80e426e79315f02fb6904f,0x003ce7e6420986df1c87895fe1b83ed86f93cf10,0x7ed71b8a343a6d4da4220123d2b3405d9e4f813f,0x3f30626d74214324e1ee6c97341abe2a9b2bdd07,0x17fb8a3dc06dc7680485871fc3ed4f8e8e662778,0x00e7b588f02d33982511ca6ab8485259bf119a2f,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/152_cofactor.csv b/src/cz/crcs/ectester/data/composite/varying/160/152_cofactor.csv
new file mode 100644
index 0000000..7861bbd
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/152_cofactor.csv
@@ -0,0 +1 @@
+0xc9d72249375ff1884a80e426e79315f02fb6904f,0x003ce7e6420986df1c87895fe1b83ed86f93cf10,0x7ed71b8a343a6d4da4220123d2b3405d9e4f813f,0x3f30626d74214324e1ee6c97341abe2a9b2bdd07,0x17fb8a3dc06dc7680485871fc3ed4f8e8e662778,0x00e7b588f02d33982511ca6ab8485259bf119a2f,0xdf
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/16.csv b/src/cz/crcs/ectester/data/composite/varying/160/16.csv
new file mode 100644
index 0000000..fd76ff7
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/16.csv
@@ -0,0 +1 @@
+0xc4bfe673203f80fd04c89a5942c18074bcc2a719,0x9d4a0edafeb576559fe95f1dfde0e006a9e0f6fb,0x2c075927ef142a14c84de72b208e8b5ee1d762b0,0x364591432aca4ab7e451866819263e32f57fa052,0x634d15df260f3bb8e92cd0d4940d176e2d97bddc,0x000000000000000000000000000000000000e77f,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/20.csv b/src/cz/crcs/ectester/data/composite/varying/160/20.csv
new file mode 100644
index 0000000..940d10c
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/20.csv
@@ -0,0 +1 @@
+0xcf8ecac9bc992d2df7ba9015b5bdcbdf2d1c2aa9,0xa067f72ab472977a150f4684df8e9ccee909489f,0x080cac1702258fce0fbafbdb4f861ad4554a05c6,0x4c4356d56316d6556e7b427a3e1aacd1c1805a8a,0x3d55e3b1904c5e66c75b00710068ffaec4a60ddb,0x00000000000000000000000000000000000d0eb3,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/25.csv b/src/cz/crcs/ectester/data/composite/varying/160/25.csv
new file mode 100644
index 0000000..318099b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/25.csv
@@ -0,0 +1 @@
+0xd3f3289b14ab182f38b78fab5dbaf3674c02597d,0xb8880d01c2b44c8a27805524913e438e6458411d,0x89482f3814165014cc30b134849ead387c7ad048,0x593ddf0087b88e469110d12067c86b00bb6f219d,0x968f74b30717f0ca56749382ba5aece4182b35d6,0x0000000000000000000000000000000001f4168b,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/2a.csv b/src/cz/crcs/ectester/data/composite/varying/160/2a.csv
new file mode 100644
index 0000000..670f4bc
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/2a.csv
@@ -0,0 +1 @@
+0x7b6d7f82beae015788a67ad391bb68ad720ba991,0x6f222dd4f5ec04fdb0202f461d10c3fa1cec6d45,0x2792a26122d154d68bdb523330a06cc252894165,0x50fa49d7061feaeec4f4f4592744d26decd6243a,0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000002,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/2b.csv b/src/cz/crcs/ectester/data/composite/varying/160/2b.csv
new file mode 100644
index 0000000..216827b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/2b.csv
@@ -0,0 +1 @@
+0xa0ba653351a6fe7af0eeb9d45eb4f5bab12e453f,0x6e2ca1be3773179e400bb31f783013138cf62eae,0x1db941d201e9dae19f2eaaef2735a46fb9948ee3,0x070fe9bde5d37d7adc7af71cdabdf99ba76b2941,0x9ad498be6e81114c204ac11300fbdd6a3ef8d2cd,0x0000000000000000000000000000000000000003,0x01 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/3.csv b/src/cz/crcs/ectester/data/composite/varying/160/3.csv
new file mode 100644
index 0000000..18ec491
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/3.csv
@@ -0,0 +1 @@
+0xd41869824871ccc03ff87bd99c9a6d2eb7c557bd,0x80b0b37638bd5678af01089dbc13a8674ad96422,0x4c2d8f41681795f138af380c86c98e1d6ee2f3a4,0x6597db8eade96de1d5a546172358d578985e4802,0xa8f85050990cbd2d365b4ef44ead757bfb9af8b5,0x0000000000000000000000000000000000000007,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/32.csv b/src/cz/crcs/ectester/data/composite/varying/160/32.csv
new file mode 100644
index 0000000..fddfeee
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/32.csv
@@ -0,0 +1 @@
+0xb13f0d997960752db0a77c95ade4843941645c87,0x7acba0516ea114053bc3e8fa026857990e610d4b,0x7f9755351f5279758bde2b9739c5f907d159ff26,0x4ce786a838268215724f1edae0ddec658ef20e6a,0xaeaa4f03aefbbf5fbaeb393ca859d8f27ca56a32,0x00000000000000000000000000000000e2768a75,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/4.csv b/src/cz/crcs/ectester/data/composite/varying/160/4.csv
new file mode 100644
index 0000000..a5b9e09
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/4.csv
@@ -0,0 +1 @@
+0xb12cff876adc5a923ed34fcd10143de02f8e0369,0x6cb241142b8fb14f45608aec44a325ad195044b5,0xa7cb4cbde8d7792bee9d4856d80df54cdc925b1f,0x07527e2751335207ab0ddb4d5692c7d9219990f5,0x1d1cd5f91fce22653562dd0534ddb861e7005cb6,0x000000000000000000000000000000000000000d,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/48.csv b/src/cz/crcs/ectester/data/composite/varying/160/48.csv
new file mode 100644
index 0000000..202a15b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/48.csv
@@ -0,0 +1 @@
+0x9f3386530aa0a8009acbbe9caa919f72c8d5730f,0x33f8b03510268eb1ca33c2996ddacec1b314c5a6,0x4d9b3a2737345fe43069f306eabdc123e8e847b2,0x0f1ca7149bc1933e1e7efdc55c325df7ad4ba562,0x3b689e90dec0b6c85d679d970278d0f9fa30f013,0x0000000000000000000000000000ca49f6d457c1,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/5.csv b/src/cz/crcs/ectester/data/composite/varying/160/5.csv
new file mode 100644
index 0000000..5f0597c
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/5.csv
@@ -0,0 +1 @@
+0xe13cc8432dad5ed8a4d2893803957c1e109e0c8f,0x7102ce05e08a10ffe665313cece127f5ff590473,0x2dcb47653c268fc7b0f767ae66fcefc98055399c,0x2c4b06f7428dda4532fbea727c7b1f84782e9762,0x4406bb147b080724d2be46eb15327dd350d7307a,0x000000000000000000000000000000000000001f,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/6.csv b/src/cz/crcs/ectester/data/composite/varying/160/6.csv
new file mode 100644
index 0000000..9c1528f
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/6.csv
@@ -0,0 +1 @@
+0xe9e74933088156a9f60b0f23253fe21ce259d783,0x6a01bdfb7c22fa778456edc767d0f61895561f27,0x27591495bbaf4845cf807f59d3091b0ec830b080,0xb956503ece30bccd9dc08bc76da995e390b2d0ea,0x30ca629aa64506f2b5e6c71fe7dea2c4284d1a2a,0x000000000000000000000000000000000000003d,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/64.csv b/src/cz/crcs/ectester/data/composite/varying/160/64.csv
new file mode 100644
index 0000000..94a2709
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/64.csv
@@ -0,0 +1 @@
+0xba824697c3ac48fbf53bdc6997a10f2e9e9d24fd,0x00878d8c00cc5b137d7ee7f3defe3ee2d614112e,0x439154313b1e0b63a3cf445a67af1f2f9442238c,0x33e0dfbcd3bdbd0a3d98254c8c706852ac9160ec,0xb0895e2997ef93d8b9500068855afeff515284c3,0x000000000000000000000000ee49fe4c5b77e201,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/7.csv b/src/cz/crcs/ectester/data/composite/varying/160/7.csv
new file mode 100644
index 0000000..170b180
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/7.csv
@@ -0,0 +1 @@
+0xb7a0a5730514d83583a708acd53a492d970022bd,0x6ee6d2a43a4daf1c0190aaf2384644b59b1c7f11,0x1835fc673409a0265da795eb4d0ad15358b3369a,0x0fee93a779b05c49623527d2a0af78315efbded6,0xb75b77ea3261bf5713cdec1cdd7251dff38232d6,0x0000000000000000000000000000000000000065,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/70.csv b/src/cz/crcs/ectester/data/composite/varying/160/70.csv
new file mode 100644
index 0000000..1dbf9c0
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/70.csv
@@ -0,0 +1 @@
+0xcc0786de97196a16f433bd40cd1932999867b103,0x7a58470e1615f4676bfc6fc57d71c99285a56919,0xa047dff6287d28be79b09ce6a398b57e8c2a97e9,0x570bda529a23c0a651113cdb5083439d3a6fd30c,0x9d71ecbe74fb180d08a7bdbb77e6aad40d2146b7,0x00000000000000000000003ba788abd620e775e7,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/8.csv b/src/cz/crcs/ectester/data/composite/varying/160/8.csv
new file mode 100644
index 0000000..232df05
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/8.csv
@@ -0,0 +1 @@
+0xc9d72249375ff1884a80e426e79315f02fb6904f,0x003ce7e6420986df1c87895fe1b83ed86f93cf10,0x7ed71b8a343a6d4da4220123d2b3405d9e4f813f,0x083e1d65a5ebcf6f98f2202ea5bfe021db0ce40e,0x16947d2cf97c654222c015b6ff56b9471f9518a9,0x00000000000000000000000000000000000000df,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/80.csv b/src/cz/crcs/ectester/data/composite/varying/160/80.csv
new file mode 100644
index 0000000..da082ef
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/80.csv
@@ -0,0 +1 @@
+0xd84ff9bc6df5a2f01d087f4c5e35ae905eb55e13,0xa50dbf4c40d4455f045c249b655b146d5d07a8a3,0xd6aed5bd031f7c3af319cdf03d45ee1b2e5c72ae,0x3a2b110757656c93362455ad480d38207b826d38,0x9cf1881da1e1f10777900f8c18996e8fbd3e470f,0x00000000000000000000e74bbc29baa61aca49d1,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/90.csv b/src/cz/crcs/ectester/data/composite/varying/160/90.csv
new file mode 100644
index 0000000..d67e673
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/90.csv
@@ -0,0 +1 @@
+0xcc0786de97196a16f433bd40cd1932999867b103,0x7a58470e1615f4676bfc6fc57d71c99285a56919,0xa047dff6287d28be79b09ce6a398b57e8c2a97e9,0x353f1f34902fb9c28b62c145369afa64b301e48c,0x0fd9c5d52882c2af8b99b5209bd80e44839c2e2e,0x0000000000000000036b917bc29fe57e7df01d13,0x01
diff --git a/src/cz/crcs/ectester/data/composite/varying/160/96.csv b/src/cz/crcs/ectester/data/composite/varying/160/96.csv
new file mode 100644
index 0000000..5dd2d5c
--- /dev/null
+++ b/src/cz/crcs/ectester/data/composite/varying/160/96.csv
@@ -0,0 +1 @@
+0xba824697c3ac48fbf53bdc6997a10f2e9e9d24fd,0x00878d8c00cc5b137d7ee7f3defe3ee2d614112e,0x439154313b1e0b63a3cf445a67af1f2f9442238c,0x5fb9809c2f608e2fb788c735d0233b2dd1cbc243,0x4e71dd0a87b3d4ff1689a77829ba527781f21cbd,0x0000000000000000c85f0b3dd7355b3a516de59b,0x01
diff --git a/src/cz/crcs/ectester/data/degenerate/brainpool.xml b/src/cz/crcs/ectester/data/degenerate/brainpool.xml
new file mode 100644
index 0000000..3dd2f54
--- /dev/null
+++ b/src/cz/crcs/ectester/data/degenerate/brainpool.xml
@@ -0,0 +1,362 @@
+<pubkey>
+ <id>brainpoolP160r1/0</id>
+ <inline>0x0000000000000000000000000000000000000000,0xe95e4a5f737059dc60dfc7ad95b3d8139515620e</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160r1/1</id>
+ <inline>0x0000000000000000000000000000000000000000,0x3290e9c18a987fec8da975f2433060ce9a5d67a4</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160r1/2</id>
+ <inline>0x0000000000000000000000000000000000000000,0xb70d585c2b880eb1dfdf91e77b37f1b755c8f73d</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>degenerate order = 7</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160r1/3</id>
+ <inline>0x0000000000000000000000000000000000000000,0xd6dcfdaf8654e853148d03b11a346873bda99f78</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>degenerate order = 53</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160r1/4</id>
+ <inline>0x0000000000000000000000000000000000000000,0x132024d2fa2b15b992fd336077f7da8644367c84</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>degenerate order = 82977018063719683</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160r1/5</id>
+ <inline>0x0000000000000000000000000000000000000000,0x5cad9ba4b9e18c1d1167683b8d2e89340cb7391f</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>degenerate order = 136095069548351808925828417</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160r1/gen</id>
+ <inline>0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000003</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>brainpoolP192r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xc302f41d932a36cda7a3463093d18db78fce476de1a86296</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192r1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xc2d59e85f6c3b8e1f01fc05f5185f332c44928215c7713b2</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192r1/2</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x5e649a10e22dbb7f226426a753c977dc23ed974d33107dde</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>degenerate order = 7</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192r1/3</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x87c26e71982b23eb6e9df053ad929f67dbd26566729d303e</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>degenerate order = 51326679042491</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192r1/4</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x28bd61f0833fb3c4106cbba35c74280bdb897ffb4ef1663d</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>degenerate order = 2218130291019312052925190546351456293022253</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192r1/gen</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000007</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>brainpoolP224r1/0</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0fe</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/1</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x5d0ee8269faa5766328ef18457528c874c408f5dd8b9991c005894ae</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/2</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x9fae816f63ae358d9ab07d30aed377ca63572c8b1cb1f982af33496c</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 5</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/3</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x1dfa7dc36ec72696d874d99b8b09013ce924820fdecaa1bd9cd09b7e</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 11</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/4</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x5267eb8a73ff20d570e131f6a0a33558c3a85cbecb51d7e4f4104132</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 89</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/5</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x92d82ad4ea31d2c90853b5a0da3f3dd233ebfbee9ef3e4eb4269846f</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 257</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/6</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0xc09fd12cf48c63d65e152f6a208bb2ab4eb003e1d9ddeb17d599a54c</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 1091</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/7</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x6af88537440e290df74852480f628ce983f542958c08768592e44dfa</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 2713</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/8</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x6e85c24f03a0dbdd4e4ddfe8a3c7b335f7bfeb83d6fecf3a9c1c23e6</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 6553</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/9</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0xb60e89dbc1fedacb81b2e172db5ec0b7ad6b797786582113b56d6955</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 1322801685354439</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/10</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x6634b0f61120124365dc719bc583a9821a027bea6dd3b6366d216be3</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>degenerate order = 13036179062997789943375385313119191</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/gen</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000003</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>brainpoolP256r1/0</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5376</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/1</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x88dbe84830c188e78ac83f1107fbd561631bdc35d59ec7fb8ed568b12eb8dbab</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>degenerate order = 5</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/2</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x295770494572e605f3a972816bf9c65701efe08c180da9736ad216400553b2ea</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>degenerate order = 23</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/3</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x817663dd4fecc333507f8d78f9605b24196d7e212d0184f277768751c2ec4c46</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>degenerate order = 1667</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/4</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x716b3a9abe12db2eeb97c18ecb121d31eed98538c62d35fc5a28ba9b930d4ae5</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>degenerate order = 149459</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/5</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x2ddf09c88fb6f4d0ffa124121cc3a3cd34254e45a2361f4ba3c2cef5e9098d5f</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>degenerate order = 17543087</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/6</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x029af8201d9619fb12bc9238dbeeed0629fc221438893b6ca92b44d7459a9bfb</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>degenerate order = 3059213862715144055733503214373292934438943635608167530247</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/gen</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000b</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>brainpoolP320r1/0</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28fcd412b1f1b32e26</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP320r1/1</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0x762fa9e1988fdb911a91a2ee9938e0c667364417df5b2a1d470dfcb2386fc42bec7c67b3595dcd8e</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>degenerate order = 11</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP320r1/2</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0x04fe1e15fa803fdb486be596b00abc53feb2eeeb9081d5b2a539e333646138d298d36b588bfbd041</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>degenerate order = 13</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP320r1/3</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0x595c3f8fddf0bca7f722d69a59d0cf269bea1e5f1e5b0ed7ad0ae6341a30ef8733865deb5996bb37</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>degenerate order = 59</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP320r1/4</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0x85de1d0bfec99e087e3315a045261dfa7ad55e035575d61d858c7b4dc807df052b2dbfa803374020</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>degenerate order = 196907</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP320r1/5</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0x044664f95553a4e4204b3c584eed7eb3c91ae92c8ee7dc9ee37e7cc067b58688c42fa8f26f3ad828</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>degenerate order = 146208281456251399783</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP320r1/6</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0d728bc8ccd9b7fd249f959dad0b57ff028e7858deff4cf9c9d65b11e3b5bbd01b6f568be5910dd6</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>degenerate order = 2307908307480288228542246803936276549862379769663891118114524423</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP320r1/gen</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000005</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>brainpoolP384r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec52</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x70269a7b61909d9fbdc89c77a359c168b31f40d488f4a817f2811d0aeda71aec407ecb8d2d561af30e52ab55bb126ae9</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/2</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x3ef4b5a9b5525a600cdfd481ff13dbeacb9f25f29af360d0e9bed208a4b650f9a26bbe89248d3bf7bc5cfd1bf1108054</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 5</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/3</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x8ca0a25e4fbf0d7b69585acdd9cb26f2cc2e6036061a960c9f342c0c2f2bef9ce8d410df3da73f2955f82dc6cfede0f6</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 11</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/4</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x7ca77491eca28a1dd1667da80aa95ecbe84ba9e379e12d1d30482790c43dcd59a0e0e2e8fad09dac4ead54b18e4911b2</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 79</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/5</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x34d6057691520ed040a958956ee8821efffa9f4827f8507b9f7d86ffdccee6a09a866839b9b631fae9b330ece487a1fb</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 734647</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/6</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x8c1e0c36b3dd4de379143acb43f078cb211543f95d85405fbcc2474f6c88701d5aece6c92d8d21e2b7b42be1e7da67b3</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 27093605140967</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/7</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x7d712d6ebcceb876c1f40263ad5c952cf2264c660c17d4567a24dfb776cd94182560094ab0f1353341851079bfdf99bd</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 3012146720727260651</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/8</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x84cf53d9ffa36b9300dcf53a1db4030f5afba0c2b5299685620432993772359358ccef721662b7d6b679207517b52817</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>degenerate order = 13857381403312519376221497559214358876512960238914501360589056738895920081</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP384r1/gen</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>brainpoolP512r1/0</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f2</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP512r1/1</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x177c47f1f2bd3306efe5a93ed046a559abbb32424d5887e6c3f49c23c907c5a3b68aee1d7ae4247ba3491698c3c7c4dd9e105383f58984e45b4104cce042417b</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>degenerate order = 7</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP512r1/2</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x9b9e9905d13f35cc5b6578523e0380be922803fa98bcde94c920aca572a8fb4a432520b51b0f9eb3d854aa14aa5ef9fcc4ac08bf06eaec4b98ffdf90244f67d7</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>degenerate order = 61</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP512r1/3</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x77b03a217034dd2adcbcbfbdfe879b4ce1f0ecdd6025d1c3da80bef3e905a34bfdcb88362d553219b025cb8123698296c437411ecba452db94d829729def073e</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>degenerate order = 329430728783919403</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP512r1/4</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x890e0b1d03bd78442f0144b752cce879cec7a069497a83a6dac714a37221fa282ef147385b796653c2b98c87c003a7285ee98f69ed3df135c6a59adf8f17be5a</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>degenerate order = 18335424362847464339</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP512r1/5</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x25c0f1328c75876e338e66fb112cd47e8936c41b57dbf2c97de9c6bf300fb035bbcb20fb44046e6172c00939075da436b9c7d84941a9b98219fced6d9e17da64</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>degenerate order = 120179186709126902983513742993</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP512r1/6</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x1d93c72f487fc4ad34cb0c522dda3a7067b1b5c11175fc90ebbd086f639cad2d30d345e5596a93136e48aad4226cdb1a320e4b0aa68da2ca62cd5fe51c601f8e</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>degenerate order = 14435454750020088047685444818571282397270727096595623715684950293729763357371155607979</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP512r1/gen</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+
diff --git a/src/cz/crcs/ectester/data/degenerate/keys.xml b/src/cz/crcs/ectester/data/degenerate/keys.xml
new file mode 100644
index 0000000..cbeecce
--- /dev/null
+++ b/src/cz/crcs/ectester/data/degenerate/keys.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE keys [
+ <!ENTITY secg SYSTEM "degenerate/secg.xml">
+ <!ENTITY brainpool SYSTEM "degenerate/brainpool.xml">
+ ]>
+<keys xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../schema.xsd"
+ category="degenerate"
+ desc="">
+ <!--
+ This is messy and what not, but Java XML api doesn't support
+ the XInclude selector necessary to make this work nicely, so XInclude is out...
+ -->
+ &secg;
+ &brainpool;
+</keys> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/degenerate/secg.xml b/src/cz/crcs/ectester/data/degenerate/secg.xml
new file mode 100644
index 0000000..7d6bce8
--- /dev/null
+++ b/src/cz/crcs/ectester/data/degenerate/secg.xml
@@ -0,0 +1,628 @@
+<pubkey>
+ <id>secp112r1/0</id>
+ <inline>0x0000000000000000000000000000,0xdb7c2abf62e35e668076bead208a</inline>
+ <curve>secg/secp112r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp112r1/1</id>
+ <inline>0x0000000000000000000000000000,0x75087e0bcdb604d9ca3a0998a8f6</inline>
+ <curve>secg/secp112r1</curve>
+ <desc>degenerate order = 23</desc>
+</pubkey>
+<pubkey>
+ <id>secp112r1/2</id>
+ <inline>0x0000000000000000000000000000,0x9ceca7fd3423a8580f4d8be19b71</inline>
+ <curve>secg/secp112r1</curve>
+ <desc>degenerate order = 452873</desc>
+</pubkey>
+<pubkey>
+ <id>secp112r1/3</id>
+ <inline>0x0000000000000000000000000000,0x250b6a43ac8a790cf22b7cdb36bd</inline>
+ <curve>secg/secp112r1</curve>
+ <desc>degenerate order = 213692946505768378488901547</desc>
+</pubkey>
+<pubkey>
+ <id>secp112r1/gen</id>
+ <inline>0x0000000000000000000000000000,0x0000000000000000000000000005</inline>
+ <curve>secg/secp112r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp128r1/0</id>
+ <inline>0x00000000000000000000000000000000,0xfffffffdfffffffffffffffffffffffe</inline>
+ <curve>secg/secp128r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp128r1/1</id>
+ <inline>0x00000000000000000000000000000000,0x0a50650222aa47d2cd1077082c2b77a1</inline>
+ <curve>secg/secp128r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>secp128r1/2</id>
+ <inline>0x00000000000000000000000000000000,0x5acdd440659ebf4945f5e131da2097c4</inline>
+ <curve>secg/secp128r1</curve>
+ <desc>degenerate order = 7</desc>
+</pubkey>
+<pubkey>
+ <id>secp128r1/3</id>
+ <inline>0x00000000000000000000000000000000,0x86ba614538631a14c10485c80d2e52aa</inline>
+ <curve>secg/secp128r1</curve>
+ <desc>degenerate order = 2700653704464143955832110573370478657</desc>
+</pubkey>
+<pubkey>
+ <id>secp128r1/gen</id>
+ <inline>0x00000000000000000000000000000000,0x00000000000000000000000000000003</inline>
+ <curve>secg/secp128r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp160r2/0</id>
+ <inline>0x0000000000000000000000000000000000000000,0xfffffffffffffffffffffffffffffffeffffac72</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r2/1</id>
+ <inline>0x0000000000000000000000000000000000000000,0x9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r2/2</id>
+ <inline>0x0000000000000000000000000000000000000000,0x508a8264d56922add3cd40482649d840497476e8</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>degenerate order = 5</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r2/3</id>
+ <inline>0x0000000000000000000000000000000000000000,0x36aec30a63930538841d0324a54aecf4f89bf859</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>degenerate order = 7</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r2/4</id>
+ <inline>0x0000000000000000000000000000000000000000,0xd2204d87c083aa9062de5c195c88de10d5f82f39</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>degenerate order = 113</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r2/5</id>
+ <inline>0x0000000000000000000000000000000000000000,0xaf2fb7626db439a172b14b80a13f4f871d0aaf97</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>degenerate order = 61588775277324185343602394973294691093621473</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r2/gen</id>
+ <inline>0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000002</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp160r1/0</id>
+ <inline>0x0000000000000000000000000000000000000000,0xffffffffffffffffffffffffffffffff7ffffffe</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/1</id>
+ <inline>0x0000000000000000000000000000000000000000,0x5286e47bcbf86e7587ca6053773787924c765eb8</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/2</id>
+ <inline>0x0000000000000000000000000000000000000000,0x6c391d32e5649a5a9fdd84584abc45d0e3604ad0</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>degenerate order = 19</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/3</id>
+ <inline>0x0000000000000000000000000000000000000000,0x26c2e1fa26e422ee36b7cdf067cd73278d1d2da4</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>degenerate order = 115901</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/4</id>
+ <inline>0x0000000000000000000000000000000000000000,0xffcb6408974e4377c57bd619ef22e839bc025fe1</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>degenerate order = 6030259</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/5</id>
+ <inline>0x0000000000000000000000000000000000000000,0x14cc0ef773488d788c437edb4e462689cb9e6004</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>degenerate order = 104179991</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/6</id>
+ <inline>0x0000000000000000000000000000000000000000,0xbdaa241dd40b0d7df97b00b41170fcb4a6fdabf9</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>degenerate order = 176070659401435712181211511</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/gen</id>
+ <inline>0x0000000000000000000000000000000000000000,0x0000000000000000000000000000000000000003</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp192r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xfffffffffffffffffffffffffffffffefffffffffffffffe</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp192r1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x2f9fe7a38e825c1f01de3418bc1d118d66ed4626e89a9b62</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>degenerate order = 59</desc>
+</pubkey>
+<pubkey>
+ <id>secp192r1/2</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x9fbf41aed6e2e0ef99359b0316f6645402f602a520af5e3f</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>degenerate order = 149309</desc>
+</pubkey>
+<pubkey>
+ <id>secp192r1/3</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x8c89aea49b8b009d7f0d0e3af71bdd9bba9fbde0fabc5f9e</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>degenerate order = 11393611</desc>
+</pubkey>
+<pubkey>
+ <id>secp192r1/4</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xbfc817a4572bbd90b5a1b7bdcc3f2822d79fc8445541b033</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>degenerate order = 108341181769254293</desc>
+</pubkey>
+<pubkey>
+ <id>secp192r1/5</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xef8804cd3326d6354ecc3ec957019d8fde73325cf7ffd877</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>degenerate order = 288626509448065367648032903</desc>
+</pubkey>
+<pubkey>
+ <id>secp192r1/gen</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000b</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp192k1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xfffffffffffffffffffffffffffffffffffffffeffffee36</inline>
+ <curve>secg/secp192k1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp192k1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xbb85691939b869c1d087f601554b96b80cb4f55b35f433c2</inline>
+ <curve>secg/secp192k1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>secp192k1/2</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x52bc2dde06d9be0fca70e761d5f395852750edf7e5ded184</inline>
+ <curve>secg/secp192k1</curve>
+ <desc>degenerate order = 7</desc>
+</pubkey>
+<pubkey>
+ <id>secp192k1/3</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x0e79be49b05f5ac28e2ac611eeafb14a4c75900d643ff5fe</inline>
+ <curve>secg/secp192k1</curve>
+ <desc>degenerate order = 11</desc>
+</pubkey>
+<pubkey>
+ <id>secp192k1/4</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xc06c0ad9b66541332b54f95c96021bfb6d6edfccc3c01c6a</inline>
+ <curve>secg/secp192k1</curve>
+ <desc>degenerate order = 1295233555201613</desc>
+</pubkey>
+<pubkey>
+ <id>secp192k1/5</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0xf73770178fa1a34019c04218683af4621b41b80e9669f2a5</inline>
+ <curve>secg/secp192k1</curve>
+ <desc>degenerate order = 10489845818524887021689201254173392444641</desc>
+</pubkey>
+<pubkey>
+ <id>secp192k1/gen</id>
+ <inline>0x000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000003</inline>
+ <curve>secg/secp192k1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp224r1/0</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0xffffffffffffffffffffffffffffffff000000000000000000000000</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/1</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x94353937171b8337606664f1900be8995691cf49934d5551cc5ace29</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/2</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0xa2bd9c773c593dd8031caa9a1d9f6483b4731af7167d6d795e0d9e9f</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 5</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/3</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0xf15055c151148708a733ec4650e58279fb849e792c4af526f029729a</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 17</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/4</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0xef92abfcfef7401f48b092a12e1abd4834f0de67a8fabccfec740794</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 257</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/5</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x3acd587a1347c0b6b0e94dc195e63cae7bd568649255ea00f8c3f844</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 641</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/6</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x7515e65e8ab6e99753c979b6b111d4dd7f9a5cc17ef79d43924b38a9</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 65537</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/7</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x872df407d9718cf23e4a9b3da9226accec9cf29f4fb1d287f222c841</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 274177</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/8</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x3012a7ffd8177bfdc61e62209414d3ec85bf25334e231f9dec255211</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 6700417</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/9</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0xf366138e28cf4ac57586d5759a79949fa71225114a8925cf21a2ae35</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>degenerate order = 67280421310721</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/gen</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000016</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp256r1/0</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0xffffffff00000001000000000000000000000000fffffffffffffffffffffffe</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/1</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x4d6ea8928adb86cf62388a8e0ef623312e68c59bdef3e53fd964598eb819acce</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/2</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x0dc5b3bf9607f9854b836abbd19428f556a1cea2ebb7a71e3e71710ffa4f2b0e</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 5</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/3</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x04b8252e44493fb6f06c6b88e3c665c9f0d470cc964557955b267519f531a262</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 17</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/4</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0xd18ddce5e27dd6a457c4ab955e351bb61b4d8d796ef679744fc0554baa8d8fc2</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 257</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/5</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0xa319d26b19bcd46157ff4f68c57b3a3f780dd35a9df3dd4a4991ea6fffa0d54e</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 641</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/6</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0xc0875c9f1d579d82da2e2e3bf14cb1f836852a2349501fd82ded6f8e772301c7</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 1531</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/7</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0xef45524f9bdfa9473bb8020719dbc64297b7f80ea1939fb69041e799d3d5c977</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 65537</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/8</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x69214c4575b40595c02c63b57fb6de6ce6bb01e34c4a7a4cfa38fa917d3b5f74</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 490463</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/9</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0xc01fe1a04efa7f9e140ccea80e206c138fa68f40900d0b75b36241e4a05f8d40</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 6700417</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/10</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0xcf8f641aa234fe4b4e4d2620abc597a13300e19bcfa247ec3c33123ce7d719cb</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>degenerate order = 835945042244614951780389953367877943453916927241</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/gen</id>
+ <inline>0x0000000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000000000000000000000000006</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp256k1/0</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000,0x0000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp256k1/1</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000,0x0000851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>secp256k1/2</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000,0x0000a2ab335e7a5b9784e9425431411a8f02a1e39029745c0d2567e7b217154fe2cb</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>degenerate order = 7</desc>
+</pubkey>
+<pubkey>
+ <id>secp256k1/3</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000,0x000068105a205ec4e9ceb2b1dd5285ab623cf09e207bad567e15482d24e582ff833f</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>degenerate order = 13441</desc>
+</pubkey>
+<pubkey>
+ <id>secp256k1/4</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000,0x0000212e9abc82e8709493c087cd14e2ebd253ecf3cd0abd68a2b7b766fcc2aa4ca6</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>degenerate order = 205115282021455665897114700593932402728804164701536103180137503955397371</desc>
+</pubkey>
+<pubkey>
+ <id>secp256k1/gen</id>
+ <inline>0x00000000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000003</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp384r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp384r1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0xad23fbead5a22478b4da040e57fea836a345078a37cb2c7045c3daf1de0db10dbda32da13fd3da4dcf3d95150e3522c8</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>degenerate order = 19</desc>
+</pubkey>
+<pubkey>
+ <id>secp384r1/2</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x83eb94214f07c841569b4da60430f7fc19aef03de2d2812d91ae40f9b2a7f5a83262b640fa4b31995a93869f71109783</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>degenerate order = 67</desc>
+</pubkey>
+<pubkey>
+ <id>secp384r1/3</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0xb3538721ea2a7edbae6973a8efb8f5109f49af10882e02239c90c7581c7f00f4cd892daede62ca75dd89971cedb618f0</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>degenerate order = 807145746439</desc>
+</pubkey>
+<pubkey>
+ <id>secp384r1/4</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0xab5c6abb2811893a9a7c4d0331e755786b1555daa209b805aec474a742d0cfd02c511e764f764543b394c6c7f89865e5</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>degenerate order = 19173790298027098165721053155794528970226934547887232785722672956982046098136719667167519737147526097</desc>
+</pubkey>
+<pubkey>
+ <id>secp384r1/gen</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
+
+<pubkey>
+ <id>secp521r1/0</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 2</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/1</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0032749246cef38c558b84265cbe9454c5b08624d5cb14a69636a701122712fcae5faafa042ad6c33247520b119fd582bcd5a02f43e801348f88f734ddb0b41f5b39</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 3</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/2</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01257bef538f850baff583c2dccc5da15be046297570d85a4dfa580a1fe9534b616321c5fb944fe9a7927ad420147aba2b6793e1a7ec25556c21ba0c60d1f29f7e93</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 5</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/3</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01f2f4b8697ed47692e132c92228e98f0dfe1d7b868852a7d76cf9f5c08ade0dfb5033be7c9dca15b8aa68fab9a01b35abd28b490ae8f8fcfa1a2bd50bcecbca89bc</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 11</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/4</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x001836c4a3a70b921586e1194e0a17cb438619edb43846933957b7a9dc09d0f447c6a0d3163cf3a5bc8ba2b4a55658e70602dc3512021d48ece14cd625e7ac7f5985</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 17</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/5</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01736df798237091ff59864f3fd212e01b6c496869bdc020beabf83bf656abf6fcce4c6286ea5caf1002401e1f272b1321850ad1d38e9e66abd68be0e79ad6834daa</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 31</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/6</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x011d3bf2a0312f01791ff702149a1616abb9e7cfa93f1ec4c7b9612c5204dfa8a76fcbb24a370774a2f615d98caf2964f87658de9c619b778343275a257cde6c7bab</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 41</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/7</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0085a52672e46236148b9485bcede803ffab149344b77a389c7537bb94b9df1b3a3854192fa512c6da411653f93d8db663fd4586beef48cd05208f38870fcd763f59</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 53</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/8</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01f5a1f4766a51e254ac60b54635b79f5830543199fdb957c0e161640a0f74a3fa85cced7857f26bd4be935b06d9fa535d9948f3bcbf1d2dadff3125c8807a21a6d6</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 131</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/9</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00dc13e71619071f58005d54b6b16682be219d85946ea9d199f81591f795003a508b5ea8e7a392450bc2da15673d0deb35d56ac9c10ab0887a1bdcbfd0c86d9d0213</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 157</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/10</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 521</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/11</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00309b3c9a4b45feef07448138eccff629e43e28acdb4fec0e08b0dff64e7292a076a9c733f209232968d60a7d9b7c08026865300f0c355f92021e9238b0558b483f</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 1613</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/12</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00662f3ca82bbfc958876666a9902a96f3437fb0999c8fa28490d8a51c89a1822d576ec48085e14bd55b6cf5cd89903cbe83b3eeef30ec38e1c885222ffc954e8b84</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 2731</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/13</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00f50e74a0ed52f6181c9a1c070de5f693c3d409e4e3bb668935b45d2a2cffcd4daabc6797d8914f18cdd44a13de1b71ca14fea6e611848495ced1f719395eed453f</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 8191</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/14</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0156f644f4d1c482f9c79e122733067cac22834fdb56ddec5e486bbd2e61bda8ec451cce3db115e8424793bc754744fc448b8100015a4f6b8a46b5dd38efec521841</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 42641</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/15</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x018c5c75b44635605ab7f529f86851e323612933fe10cbc72a806c2bafb86e85d254246e1c7468466cc8663cd1cc3aa44ff15ad808e729df4e75fb23da6374d48e8b</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 51481</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/16</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0043c1af0a225ffebeb76cf2d98e0480691871125d1c65304789110f60941a8e3b6265fbe338f584569f0245984050cc94afc190bcc1abc143c557609644cf10f3cf</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 61681</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/17</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00391b1adb891ad8156a8056781c9f665eb51cd4fa6837fc2a7d7d31f7161a7b94b52a7697f24e956b4eec6956d483f52efad14f581360bc8091544932bc14767a3a</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 409891</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/18</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01757c67f02f8b94f08642e00d4032a721d13a34243686fbb4cec8c0472bbda45fba8ab338b4afd7bac07260b4e8a21a8997eaee01cb5928f605ce0587138fde3e8c</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 858001</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/19</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x009297636ecc72ad872103c99fd3ed0ee94d24af2051d87d77a96df45b52ff26df768d8ddc0ce6e53d24ac482f9b3cc7b6ebf25601a47ce9ba95052a5dc80e4c79e5</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 5746001</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/20</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0130713f9de95587ba4272d1a5e996beee9530e10bd5c15e3e531a9f7ae59e0587106db1802309f49b5812e8811aa667d0ce9b838d814e984caf2833e2144dfc57b7</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 7623851</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/21</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00d08a1bd1285c19d86a1a4fd85f378bcd09a83addfdcc7e392fa9d8f9fa00b3d4af8887aff110f565c50cbc3b99bd7e5d55e051eeea5772cafb6bcec9e936de4955</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 34110701</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/22</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x00791d7f3bf9c19a1b61f8f262a2e60a22fa9adfdcc0d6afeffab8068fbd91bc079188ba0365c0fe86c92073e244294a0da331ba36ccd01dcf323e92b16d11ca2b39</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 308761441</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/23</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x0066fd8474256e396de2160ee4590caccdec49c5d099e12c7e405315a92dfb21e8277549d8d291744d79b841e8e1e86d5273fe07d3f56fed6f1c1220c2c217c289ef</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 2400573761</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/24</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01e5be0afc4fa36bc186c73de3ab924e6572d2b239887cf028af290befab2b168e7333f78a80f66525d5bd1534c8fab6b002c5ce2ac2279c1dc0f356dc199ff98c42</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 65427463921</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/25</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x019d8298bbd7449ff8e27bb3cd2243c182bd8dee40b287e903b1da711cf8f90f21b8ab497aba68fa6f252998a16eea60f6ec0a747f58dbf34e5e4544e7b392fb96ce</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 108140989558681</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/26</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01243fb23685cf51dcab5d05385275f63fd3eb2225aeb2ae3e0e0260d09e84c6a7f655ece1b14e54b17aa512c55ed94168a203bf70c908e1934f8b6fc04f971cdbfc</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 145295143558111</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/27</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x01f803543c1ed5ed182210105552c99b8df0b740f67423a960cd35327914efbf2ae2d4debd0116ffa6d726f9727123f3a2083c8f4633a6a6531afcea86b72a301c6c</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>degenerate order = 173308343918874810521923841</desc>
+</pubkey>
+<pubkey>
+ <id>secp521r1/gen</id>
+ <inline>0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>generator of Fp^*</desc>
+</pubkey>
diff --git a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160r1.xml b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160r1.xml
index fb3645e..b11c2c8 100644
--- a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160r1.xml
@@ -323,3 +323,22 @@
<curve>brainpool/brainpoolP160r1</curve>
<desc>invalid order = 251</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>brainpoolP160r1/54</id>
+ <inline>0x5440002083ce239da4933d543c4a6c2b4043d9d0,0x664f5bc313fae27ba1bb2e45ab4d5788938d1945</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160r1/55</id>
+ <inline>0x4af82c74a3420119e5a6cad2beac7299d1ff0b76,0xb53733e9a63a9df9ce745ba7282a91dcd4df63db</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160r1/56</id>
+ <inline>0x3d270e44f2a93d28ce6cdf6788f312cabfdfe80d,0xd3560c22ac8c24f223d3cf6592350549071b4830</inline>
+ <curve>brainpool/brainpoolP160r1</curve>
+ <desc>invalid order = 1231</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160t1.xml b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160t1.xml
index a712bab..5ef2693 100644
--- a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160t1.xml
+++ b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP160t1.xml
@@ -323,3 +323,22 @@
<curve>brainpool/brainpoolP160t1</curve>
<desc>invalid order = 251</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>brainpoolP160t1/54</id>
+ <inline>0x6d17b06757c690a1ae9f411261be16f402eb9413,0x4b2fd210f79990027d8ee78fedf9c467110a76f5</inline>
+ <curve>brainpool/brainpoolP160t1</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160t1/55</id>
+ <inline>0x90ab4fc73c706f7778072637ff7fa3694bbfce62,0x0eb9d9dbff4167652d410e235e9fed3acb02d955</inline>
+ <curve>brainpool/brainpoolP160t1</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP160t1/56</id>
+ <inline>0x0b7e4c6697993fa4f9fc88a5f5bf7e5bffdc8554,0xbb9fcd7e5b68d86cd841959a88a6294b725b0607</inline>
+ <curve>brainpool/brainpoolP160t1</curve>
+ <desc>invalid order = 1231</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192r1.xml b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192r1.xml
index 13fede5..6458609 100644
--- a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192r1.xml
@@ -365,3 +365,22 @@
<curve>brainpool/brainpoolP192r1</curve>
<desc>invalid order = 283</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>brainpoolP192r1/61</id>
+ <inline>0x952940885d62715784f5501451fe20f56825f449830b8e1a,0xa2786768d1b25f41c2d1a9d219faa70284b4bbe583bf006b</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192r1/62</id>
+ <inline>0x6e1bfe4453e3d7fffb26abd47a8eba7eeb601cea9b56f136,0x0549d43dafbe9b0651d9aff2fcfdc07e94c4ce07a8c75595</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192r1/63</id>
+ <inline>0x5fa6f0d37e8ab6d27aa6214bb7f4a68feb979ad8d2ce1f48,0x29a93d6ef731d6ba7ae62173d9927012ecb52cf23c45f0d6</inline>
+ <curve>brainpool/brainpoolP192r1</curve>
+ <desc>invalid order = 1231</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192t1.xml b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192t1.xml
index 046e109..cf90464 100644
--- a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192t1.xml
+++ b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP192t1.xml
@@ -365,3 +365,22 @@
<curve>brainpool/brainpoolP192t1</curve>
<desc>invalid order = 283</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>brainpoolP192t1/61</id>
+ <inline>0x08ebff23b6c006a582cffd9a9aefa704cf1db3802a94cc15,0xbb823733f0afe7e09b90e537f2e395c77471851185ef837f</inline>
+ <curve>brainpool/brainpoolP192t1</curve>
+ <desc>invalid order = 419</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192t1/62</id>
+ <inline>0x3a81c7f62751a5474efdc6415087a9c73a8e0ec9aa37ae94,0x79f451441715a120f084f2040d0033c76e23fd91b5135b7b</inline>
+ <curve>brainpool/brainpoolP192t1</curve>
+ <desc>invalid order = 719</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP192t1/63</id>
+ <inline>0xa13f674583e7cf28a7db917343d52eee5021f94687d2cdc7,0x08fee687764ebdb13d1df57635aa36e1bcc5c15ab81c636a</inline>
+ <curve>brainpool/brainpoolP192t1</curve>
+ <desc>invalid order = 1531</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224r1.xml b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224r1.xml
index 8fb484c..7a12145 100644
--- a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224r1.xml
@@ -413,3 +413,22 @@
<curve>brainpool/brainpoolP224r1</curve>
<desc>invalid order = 347</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>brainpoolP224r1/69</id>
+ <inline>0x6e8f01ad3bb0efb4b64d063ce895e5b8cebb59ca2e21b51c5c03df99,0x0b9ea9eea8711e05b748ab40a000dcea18f284c4aab641ee2649ee9d</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>invalid order = 419</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/70</id>
+ <inline>0xc86fec6cd248b4f9ce398a115c01efd542cc2466d1339ebb2155334c,0x69f4038dac3a65e33c7ea5f72f667de1d866b1a9dc6b255b163fc6af</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>invalid order = 719</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224r1/71</id>
+ <inline>0xaac6e5506124b876663a417e276772c255f8f02e6b13cf01de7a799a,0x94344c04162c316132c4a57125ab9398b4089ebed5d9db2a3dbf20b4</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>invalid order = 1531</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224t1.xml b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224t1.xml
index 3e35a3e..c7ae75b 100644
--- a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224t1.xml
+++ b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP224t1.xml
@@ -413,3 +413,22 @@
<curve>brainpool/brainpoolP224t1</curve>
<desc>invalid order = 347</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>brainpoolP224t1/69</id>
+ <inline>0x96cd2668ee03c4cbb59d1de6011bdcc22935477e95f413817755bf48,0x040cc03af01e6f830694cec88cc0e0b9bcdb0033668265ac2a112d2f</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>invalid order = 419</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224t1/70</id>
+ <inline>0x8a875207d59ca2cfd415447bfdb52f15c710595862542768950e4fa4,0xaa0bfbec6318573c922cc00b73ec86761cdfc7fb959689e9df27eb14</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>invalid order = 719</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP224t1/71</id>
+ <inline>0x6dd14e731e37d6d945ad336106e16f9fd9d2d83f2ddc1dfded98643d,0x500b783f23700d0c79d25c62b2f427faa88e05cbaf8454b53295d0df</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>invalid order = 1531</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256r1.xml b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256r1.xml
index c923eae..ebd8f6b 100644
--- a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256r1.xml
@@ -461,3 +461,22 @@
<curve>brainpool/brainpoolP256r1</curve>
<desc>invalid order = 389</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>brainpoolP256r1/77</id>
+ <inline>0x573d17f1ae91154ea19e094a6b6759dde102c6eb677829ec8e7f5fc99aa1ca04,0x2f714a94b9fd5bd31bd9896b0990c09f9c64339ee1f33497760e7d52134458e2</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>invalid order = 419</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/78</id>
+ <inline>0x885a1fc959c4f094a0524b350b576d4383599bd9063b3a8fa27e2f0833695225,0x2e39483178d9253a84b38d94d9ecdc0703be70fa1c1445a0d2038b738e687996</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>invalid order = 719</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256r1/79</id>
+ <inline>0x0c58ff24e3c1c6e38f2d5e8bb4f30a6afce5d88003d48b5c930a7e3d4690652f,0x0bfd16361c8d4d12563000f88832155f172fde581a99d8e63f642ef68b63e2ba</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>invalid order = 1531</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256t1.xml b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256t1.xml
index 2f31006..c2cf345 100644
--- a/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256t1.xml
+++ b/src/cz/crcs/ectester/data/invalid/brainpool/brainpoolP256t1.xml
@@ -461,3 +461,22 @@
<curve>brainpool/brainpoolP256t1</curve>
<desc>invalid order = 389</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>brainpoolP256t1/77</id>
+ <inline>0x2bf8c11defcdac7379c1d81ab87d72d13d8b1a7a53e59a6c5eda6c5d7b615f4e,0x6bcef1b705223c36086a1a06cf6a55fecf4362c0444b4c73b8f8d402955e52fb</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>invalid order = 419</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256t1/78</id>
+ <inline>0x67e3ba2a6485080a29384ddd38f8f5a476338a7b39fe411d18c49cb5ce5a04a2,0x25e146ab0e5b3e5a6ad5dca7bcc72d9afdfaec3e2c993a9166144aa0d9fbecd4</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>invalid order = 719</desc>
+</pubkey>
+<pubkey>
+ <id>brainpoolP256t1/79</id>
+ <inline>0x93efaee7235082be3ce10f16207f91472aa336b7309edfebcfcc77182206949e,0x1ecb5b2db697f34ca887e4fe4fa00fcd9d50dff8c6183038469b67b6060f1030</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>invalid order = 1531</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp112r1.xml b/src/cz/crcs/ectester/data/invalid/secg/secp112r1.xml
index ae8da15..316f0f6 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp112r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp112r1.xml
@@ -245,3 +245,22 @@
<curve>secg/secp112r1</curve>
<desc>invalid order = 179</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>secp112r1/41</id>
+ <inline>0x8eac00cf476993c428eaf07c80f1,0x27977f0c5acb323667408f21d143</inline>
+ <curve>secg/secp112r1</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>secp112r1/42</id>
+ <inline>0x8c5a6233e53b2c6b6fcf33af2726,0x5a04f74d8b5e220e8c23d1f21bb6</inline>
+ <curve>secg/secp112r1</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>secp112r1/43</id>
+ <inline>0x5a4479a257ed4b9a519f29184712,0x58c11aa81217d4ce67d8f05da930</inline>
+ <curve>secg/secp112r1</curve>
+ <desc>invalid order = 1231</desc>
+</pubkey>
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp112r2.xml b/src/cz/crcs/ectester/data/invalid/secg/secp112r2.xml
index 9dc187e..536cb56 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp112r2.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp112r2.xml
@@ -245,3 +245,22 @@
<curve>secg/secp112r2</curve>
<desc>invalid order = 179</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>secp112r2/41</id>
+ <inline>0x6fffe4ca3cbda6828ddd63e9ab11,0xcf5e055aa2a94c0d7214d998c3a0</inline>
+ <curve>secg/secp112r2</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>secp112r2/42</id>
+ <inline>0x3813064a869de8884025d85736c0,0xd71ae54681ffc105144c8f7ba5bb</inline>
+ <curve>secg/secp112r2</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>secp112r2/43</id>
+ <inline>0x6906e5609f3d9e47c7cd961dc08e,0x7fccd8384db6b6fcc842a4f397fd</inline>
+ <curve>secg/secp112r2</curve>
+ <desc>invalid order = 1231</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp128r1.xml b/src/cz/crcs/ectester/data/invalid/secg/secp128r1.xml
index f038656..76f0aff 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp128r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp128r1.xml
@@ -269,3 +269,21 @@
<curve>secg/secp128r1</curve>
<desc>invalid order = 197</desc>
</pubkey>
+<pubkey>
+ <id>secp128r1/45</id>
+ <inline>0xea08890b70e94ac5d53514b583580faf,0x6cc66b4eedab2a8f01a0b41195271853</inline>
+ <curve>secg/secp128r1</curve>
+ <desc>invalid order = 359</desc>
+</pubkey>
+<pubkey>
+ <id>secp128r1/46</id>
+ <inline>0x0ae9c73132e5ef2fd82d06b0f50bfe64,0x9b78c29bdf53038463fa4bf2edb4297a</inline>
+ <curve>secg/secp128r1</curve>
+ <desc>invalid order = 601</desc>
+</pubkey>
+<pubkey>
+ <id>secp128r1/47</id>
+ <inline>0xd3522b2fb7fd15b8fbaf10a9abc60ca9,0x21236ba59e5a40eb9881a0218a2c2359</inline>
+ <curve>secg/secp128r1</curve>
+ <desc>invalid order = 1103</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp128r2.xml b/src/cz/crcs/ectester/data/invalid/secg/secp128r2.xml
index ecb62bf..11fc0d8 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp128r2.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp128r2.xml
@@ -269,3 +269,22 @@
<curve>secg/secp128r2</curve>
<desc>invalid order = 197</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>secp128r2/45</id>
+ <inline>0x33c5f2e6190f7a3c23dbc5a1020e0f32,0x40afb310a8c5537ecc07c59d971c5fe6</inline>
+ <curve>secg/secp128r2</curve>
+ <desc>invalid order = 359</desc>
+</pubkey>
+<pubkey>
+ <id>secp128r2/46</id>
+ <inline>0xd5392aed70323f8a02ec104dbd3dd3f2,0x0733de2e9d20bb117a632a9b5ff3c1a3</inline>
+ <curve>secg/secp128r2</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>secp128r2/47</id>
+ <inline>0x005a0ea68afd5793063d4537045e5cba,0x6ec5978352c81a646fc1b29491a62a59</inline>
+ <curve>secg/secp128r2</curve>
+ <desc>invalid order = 1103</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp160r1.xml b/src/cz/crcs/ectester/data/invalid/secg/secp160r1.xml
index 10fc5a0..c9ae8da 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp160r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp160r1.xml
@@ -323,3 +323,22 @@
<curve>secg/secp160r1</curve>
<desc>invalid order = 251</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>secp160r1/54</id>
+ <inline>0x8932e643678c5a324d7a2cf47528676d08f135d5,0x3a6a976e51623bf13d8d339312e2e65c9b29ea04</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/55</id>
+ <inline>0xaee7bf31f3d12332e5e529eb0a7732ac913d0211,0xaa88ae4645cac4e7970a764e486774b2398e9fd0</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>invalid order = 613</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r1/56</id>
+ <inline>0xc0a7736e7eec336eb3b7f853a832d4eec1d6f33f,0x2d7c536a1ee9cca9bb504755225c678f64ed5275</inline>
+ <curve>secg/secp160r1</curve>
+ <desc>invalid order = 1123</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp160r2.xml b/src/cz/crcs/ectester/data/invalid/secg/secp160r2.xml
index 596fc6c..b1658c5 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp160r2.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp160r2.xml
@@ -323,3 +323,22 @@
<curve>secg/secp160r2</curve>
<desc>invalid order = 251</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>secp160r2/54</id>
+ <inline>0x15567f6e8e2d4a71ed809adbd53c620b3d674ca4,0xb418ff9fdc1eb410dd53064090099e76473d3f61</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r2/55</id>
+ <inline>0x490905f64c868304641864ca9ad90fa48475f765,0xb52e302f7fe9c63a9bf6124daff99e7e3c7f9fda</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>invalid order = 613</desc>
+</pubkey>
+<pubkey>
+ <id>secp160r2/56</id>
+ <inline>0x1de73470d9a5ed4c6bb7a4c162956d20c1c2a38a,0x8037b163763d4dfd2d218f7d85d17c06bfa07ecc</inline>
+ <curve>secg/secp160r2</curve>
+ <desc>invalid order = 1123</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp192r1.xml b/src/cz/crcs/ectester/data/invalid/secg/secp192r1.xml
index 151189e..e823fed 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp192r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp192r1.xml
@@ -371,3 +371,22 @@
<curve>secg/secp192r1</curve>
<desc>invalid order = 293</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>secp192r1/62</id>
+ <inline>0x64f88f2014026439717b443fd0e9656bae76bc12e04846a6,0xed20d8d4ee021c98be74fdfd4e545fb8b8e529f269f6059e</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>secp192r1/63</id>
+ <inline>0xeed3216e47d486fc7d1717e5732e1ef5409b84a0777df50a,0x20b7bcc21f15418b75ef425fcb0c7caf87c9ccad70e06142</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>secp192r1/64</id>
+ <inline>0xc26950fdd51d386cf3c9d8e3e78c33e10e1046bfd5c41d8a,0x8bea331f38d09138dd75f414466db8c13948f8c6ddcc5def</inline>
+ <curve>secg/secp192r1</curve>
+ <desc>invalid order = 1231</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp224r1.xml b/src/cz/crcs/ectester/data/invalid/secg/secp224r1.xml
index aea9831..3f8c8fc 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp224r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp224r1.xml
@@ -413,3 +413,22 @@
<curve>secg/secp224r1</curve>
<desc>invalid order = 347</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>secp224r1/69</id>
+ <inline>0x21224a2e74c519b044cb0885bb4d39c93d459cb810a486e2bd257380,0xfcf0f5c414e98767bdd0a95887aa065634102f61afcbe13b7f1918c9</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/70</id>
+ <inline>0xc81155743c1ce0d22f9bbc7acf64666e1e82973866c63e7e10a295c3,0x83ddf0ad6ed67e8863f3830e0ef6e76857b2d21d6de3ce9bc60153a0</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>secp224r1/71</id>
+ <inline>0x74c39d25aaff45aea0a1e2a1f76ce58fc56bfff0b92f21ecea29b582,0x9a1f6fee02efe3a3013501fb4b77f9f6e6ca633463809207319a0787</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>invalid order = 1231</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/invalid/secg/secp256r1.xml b/src/cz/crcs/ectester/data/invalid/secg/secp256r1.xml
index 6f93370..2c23ea7 100644
--- a/src/cz/crcs/ectester/data/invalid/secg/secp256r1.xml
+++ b/src/cz/crcs/ectester/data/invalid/secg/secp256r1.xml
@@ -461,3 +461,22 @@
<curve>secg/secp256r1</curve>
<desc>invalid order = 389</desc>
</pubkey>
+<!-- Additional points of larger order. -->
+<pubkey>
+ <id>secp256r1/77</id>
+ <inline>0xb1b630092fa728b962bda086704dd16628d8ba65a5836f0e5ab6b268b1874346,0x6741a8de59e27d93c2afe35d02a62a0d6ca1d410f02fa272c916457c3d64024e</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>invalid order = 353</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/78</id>
+ <inline>0x8ccf453921033e2a0e2d612103f9d6037bede19bce172bc7e4cfab350dba5c1b,0x4f381c96db7205602819de572b088b81cd8aad51dec5367b2572d07ec174b13b</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>invalid order = 631</desc>
+</pubkey>
+<pubkey>
+ <id>secp256r1/79</id>
+ <inline>0xed9c0943430dbb23b735c527f5376eb1f159ce7ed42d725f89b03d2b4004dd93,0xc8e98a510b4d1988d8291c4f59b99894285b0a18801ec46e1d732c37fbbe6027</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>invalid order = 1231</desc>
+</pubkey> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/other/curve25519.csv b/src/cz/crcs/ectester/data/other/curve25519.csv
new file mode 100644
index 0000000..2e62d80
--- /dev/null
+++ b/src/cz/crcs/ectester/data/other/curve25519.csv
@@ -0,0 +1 @@
+0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED,0x2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144,0x7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864,0x2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A,0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9,0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED,0x02 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/other/curves.xml b/src/cz/crcs/ectester/data/other/curves.xml
new file mode 100644
index 0000000..f200d9c
--- /dev/null
+++ b/src/cz/crcs/ectester/data/other/curves.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<curves xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../schema.xsd">
+ <curve>
+ <id>M-221</id>
+ <bits>221</bits>
+ <field>prime</field>
+ <file>m221.csv</file>
+ <desc>Montgomery M-221 curve from eprint 2013/647, transformed into short Weierstrass form</desc>
+ </curve>
+ <curve>
+ <id>M-383</id>
+ <bits>383</bits>
+ <field>prime</field>
+ <file>m383.csv</file>
+ <desc>Montgomery M-383 curve from eprint 2013/647, transformed into short Weierstrass form</desc>
+ </curve>
+ <curve>
+ <id>M-511</id>
+ <bits>511</bits>
+ <field>prime</field>
+ <file>m511.csv</file>
+ <desc>Montgomery M-511 curve from eprint 2013/647, transformed into short Weierstrass form</desc>
+ </curve>
+
+ <curve>
+ <id>Curve25519</id>
+ <bits>256</bits>
+ <field>prime</field>
+ <file>curve25519.csv</file>
+ <desc>Curve25519 transformed into short Weierstrass form</desc>
+ </curve>
+</curves> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/other/m221.csv b/src/cz/crcs/ectester/data/other/m221.csv
new file mode 100644
index 0000000..0a74263
--- /dev/null
+++ b/src/cz/crcs/ectester/data/other/m221.csv
@@ -0,0 +1 @@
+0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD,0x155555555555555555555555555555555555555555555554451FF4F3,0x1684BDA12F684BDA12F684BDA12F684BDA12F684BDA19B7249700DF7,0x1555555555555555555555555555555555555555555555555555EDC0,0x0F7ACDD2A4939571D1CEF14ECA37C228E61DBFF10707DC6C08C5056D,0x040000000000000000000000000015A08ED730E8A2F77F005042605B,0x4
diff --git a/src/cz/crcs/ectester/data/other/m383.csv b/src/cz/crcs/ectester/data/other/m383.csv
new file mode 100644
index 0000000..9a8890d
--- /dev/null
+++ b/src/cz/crcs/ectester/data/other/m383.csv
@@ -0,0 +1 @@
+0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45,0x2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA95FABD1AE6C,0x04BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684BDA12F7159AE18A4923F45,0x5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555FD5E4,0x1EC7ED04AAF834AF310E304B2DA0F328E7C165F0E8988ABD3992861290F617AA1F1B2E7D0B6E332E969991B62555E77E,0x10000000000000000000000000000000000000000000000006C79673AC36BA6E7A32576F7B1B249E46BBC225BE9071D7,0x02
diff --git a/src/cz/crcs/ectester/data/other/m511.csv b/src/cz/crcs/ectester/data/other/m511.csv
new file mode 100644
index 0000000..815714c
--- /dev/null
+++ b/src/cz/crcs/ectester/data/other/m511.csv
@@ -0,0 +1 @@
+0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45,0x2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA94D474F50C,0x425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED0BEFAE0163491C0,0x2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD5D1E,0x2FBDC0AD8530803D28FDBAD354BB488D32399AC1CF8F6E01EE3F96389B90C809422B9429E8A43DBF49308AC4455940ABE9F1DBCA542093A895E30A64AF056FA5,0x100000000000000000000000000000000000000000000000000000000000000017B5FEFF30C7F5677AB2AEEBD13779A2AC125042A6AA10BFA54C15BAB76BAF1B,0x02
diff --git a/src/cz/crcs/ectester/data/schema.xsd b/src/cz/crcs/ectester/data/schema.xsd
index 2fe7892..85e8107 100644
--- a/src/cz/crcs/ectester/data/schema.xsd
+++ b/src/cz/crcs/ectester/data/schema.xsd
@@ -61,10 +61,11 @@
<xs:simpleType name="kaType">
<xs:restriction base="xs:string">
<xs:enumeration value="DH"/>
- <xs:enumeration value="ECDH"/>
<xs:enumeration value="DHC"/>
- <xs:enumeration value="ECDHC"/>
- <xs:enumeration value="BOTH"/>
+ <xs:enumeration value="DH_PLAIN"/>
+ <xs:enumeration value="DHC_PLAIN"/>
+ <xs:enumeration value="PACE_GM"/>
+ <xs:enumeration value="DH_PLAIN_XY"/>
<xs:enumeration value="ANY"/>
</xs:restriction>
</xs:simpleType>
diff --git a/src/cz/crcs/ectester/data/supersingular/curves.xml b/src/cz/crcs/ectester/data/supersingular/curves.xml
new file mode 100644
index 0000000..186a8a7
--- /dev/null
+++ b/src/cz/crcs/ectester/data/supersingular/curves.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<curves xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../schema.xsd">
+ <curve>
+ <id>ss128</id>
+ <bits>128</bits>
+ <field>prime</field>
+ <file>ss128.csv</file>
+ <desc>Supersingular curve</desc>
+ </curve>
+ <curve>
+ <id>ss192</id>
+ <bits>192</bits>
+ <field>prime</field>
+ <file>ss192.csv</file>
+ <desc>Supersingular curve</desc>
+ </curve>
+ <curve>
+ <id>ss224</id>
+ <bits>224</bits>
+ <field>prime</field>
+ <file>ss224.csv</file>
+ <desc>Supersingular curve</desc>
+ </curve>
+ <curve>
+ <id>ss256</id>
+ <bits>256</bits>
+ <field>prime</field>
+ <file>ss256.csv</file>
+ <desc>Supersingular curve</desc>
+ </curve>
+</curves> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/supersingular/ss128.csv b/src/cz/crcs/ectester/data/supersingular/ss128.csv
new file mode 100644
index 0000000..9dd4f13
--- /dev/null
+++ b/src/cz/crcs/ectester/data/supersingular/ss128.csv
@@ -0,0 +1 @@
+0x9ad6ed2af5bd6f3a9ac1d052ea17b2a9,0x8a3fe60aedb247e20a2d0c4a07de4d37,0x10970720080b27589094c408e2396572,0x563804cbd66f054434143af1e3ec6eaf,0x42af7ba7a078ef8fa3c0f253d1ccc16a,0x4d6b76957adeb79d4d60e829750bd955,0x02 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/supersingular/ss192.csv b/src/cz/crcs/ectester/data/supersingular/ss192.csv
new file mode 100644
index 0000000..0c8ae8b
--- /dev/null
+++ b/src/cz/crcs/ectester/data/supersingular/ss192.csv
@@ -0,0 +1 @@
+0x8c4dbc0e122afdeb466c2b7c3321e72531ac1cd8435f5159,0x64ff701953d8a795e3d9fa41a85eb2bd355479744198ae6c,0x274e4bf4be5256556292313a8ac33467fc57a36401c6a2ed,0x6c39b62a8665aca35dc1669dd483a1e881c65557bbed7f8c,0x1f90241e9bdb361251343bf4cb1ff19545e1e0fff2c8f235,0x4626de0709157ef5a33615be1990f39298d60e6c21afa8ad,0x02 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/supersingular/ss224.csv b/src/cz/crcs/ectester/data/supersingular/ss224.csv
new file mode 100644
index 0000000..01eaa35
--- /dev/null
+++ b/src/cz/crcs/ectester/data/supersingular/ss224.csv
@@ -0,0 +1 @@
+0xa52f9550f18b8475c5cddd1232428b0c6138aa8704759eab7916f839,0x35186ffe96c8460148b9070efdde881f68647ff48a93854966ebf457,0x701725525ac33e747d14d603346402ecf8d42a9279e21962122b03e2,0x726e4342d936e7c3f004d36b5a703ca35d000014e70bceb1e956f7cc,0x9b3785caa9b028340c564ec4e7450229b7a0b16bc7185c78d852e2a6,0x1084c221b1c126d893c7c94e9ea0411ad685aaa71a0bc31125b57f39,0x0a \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/supersingular/ss256.csv b/src/cz/crcs/ectester/data/supersingular/ss256.csv
new file mode 100644
index 0000000..47a8174
--- /dev/null
+++ b/src/cz/crcs/ectester/data/supersingular/ss256.csv
@@ -0,0 +1 @@
+0xf9cde8953b26ab31fe1b135266d2f9187e3d9df982880f05cc80f1998b9b0c8d,0xdf0a21f2f4d03d6ca2e151406e17cc1f0300287a348bc4452d7320db6138269e,0x1ac3c6a246566dc55b39c211f8bb2cf97b3d757f4dfc4ac09f0dd0be2a62e5ef,0x3c52f9e66b5c180923ac7bfb7f88f0162ee1dca122aa8dda1e8de3e044cb55a6,0x89c2f4437118d2edb0021706feef5a4419150afd7d1c3b7401eee93c2e547264,0x7ce6f44a9d935598ff0d89a933697c8c3f1ecefcc1440782e64078ccc5cd8647,0x02 \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/wrong/curves.xml b/src/cz/crcs/ectester/data/wrong/curves.xml
index 396dc4e..2a51474 100644
--- a/src/cz/crcs/ectester/data/wrong/curves.xml
+++ b/src/cz/crcs/ectester/data/wrong/curves.xml
@@ -6,77 +6,90 @@
<bits>128</bits>
<field>prime</field>
<file>wrongp128.csv</file>
+ <desc>The field is not prime.</desc>
</curve>
<curve>
<id>wrongp160</id>
<bits>160</bits>
<field>prime</field>
<file>wrongp160.csv</file>
+ <desc>The field is not prime.</desc>
</curve>
<curve>
<id>wrongp192</id>
<bits>192</bits>
<field>prime</field>
<file>wrongp192.csv</file>
+ <desc>The field is not prime.</desc>
</curve>
<curve>
<id>wrongp224</id>
<bits>224</bits>
<field>prime</field>
<file>wrongp224.csv</file>
+ <desc>The field is not prime.</desc>
</curve>
<curve>
<id>wrongp256</id>
<bits>256</bits>
<field>prime</field>
<file>wrongp256.csv</file>
+ <desc>The field is not prime.</desc>
</curve>
<curve>
<id>wrongp384</id>
<bits>384</bits>
<field>prime</field>
<file>wrongp384.csv</file>
+ <desc>The field is not prime.</desc>
</curve>
<curve>
<id>wrongp521</id>
<bits>521</bits>
<field>prime</field>
<file>wrongp521.csv</file>
+ <desc>The field is not prime.</desc>
</curve>
<curve>
<id>wrongt163</id>
<bits>163</bits>
<field>binary</field>
<file>wrongt163.csv</file>
+ <desc>The field polynomial is not irreducible in F_2^163[x].</desc>
</curve>
<curve>
<id>wrongt233</id>
<bits>233</bits>
<field>binary</field>
<file>wrongt233.csv</file>
+ <desc>The field polynomial is not irreducible in F_2^233[x].</desc>
</curve>
<curve>
<id>wrongt239</id>
<bits>239</bits>
<field>binary</field>
<file>wrongt239.csv</file>
+ <desc>The field polynomial is not irreducible in F_2^239[x].</desc>
</curve>
<curve>
<id>wrongt283</id>
<bits>283</bits>
<field>binary</field>
<file>wrongt283.csv</file>
+ <desc>The field polynomial is not irreducible in F_2^283[x].</desc>
</curve>
<curve>
<id>wrongt409</id>
<bits>409</bits>
<field>binary</field>
<file>wrongt409.csv</file>
+ <desc>The field polynomial is not irreducible in F_2^409[x].</desc>
</curve>
<curve>
<id>wrongt571</id>
<bits>571</bits>
<field>binary</field>
<file>wrongt571.csv</file>
+ <desc>The field polynomial is not irreducible in F_2^571[x].</desc>
</curve>
</curves> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/wycheproof/keys.xml b/src/cz/crcs/ectester/data/wycheproof/keys.xml
new file mode 100644
index 0000000..46cd697
--- /dev/null
+++ b/src/cz/crcs/ectester/data/wycheproof/keys.xml
@@ -0,0 +1,894 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<keys xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../schema.xsd"
+ category="wycheproof"
+ desc="">
+ <privkey>
+ <id>addsub/secp224r1/1s</id>
+ <inline>0x0ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c29b7</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>tcId = 34</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp224r1/1w</id>
+ <inline>0x478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac230,0x2e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504</inline>
+ <!-- 304e301006072a8648ce3d020106052b81040021033a0004478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504 -->
+ <curve>secg/secp224r1</curve>
+ <desc>tcId = 34</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp224r1/2s</id>
+ <inline>0x0ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a37</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>tcId = 35</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp224r1/2w</id>
+ <inline>0x478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac230,0x2e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504</inline>
+ <!-- 304e301006072a8648ce3d020106052b81040021033a0004478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504 -->
+ <curve>secg/secp224r1</curve>
+ <desc>tcId = 35</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp224r1/3s</id>
+ <inline>0x0ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3b</inline>
+ <curve>secg/secp224r1</curve>
+ <desc>tcId = 37</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp224r1/3w</id>
+ <inline>0x478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac230,0x2e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504</inline>
+ <!-- 304e301006072a8648ce3d020106052b81040021033a0004478e73465bb1183583f4064e67e8b4343af4a05d29dfc04eb60ac2302e5b9a3a1b32e4208d4c284ff26822e09c3a9a4683443e4a35175504 -->
+ <curve>secg/secp224r1</curve>
+ <desc>tcId = 37</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256r1/1s</id>
+ <inline>0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324f3</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 106</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256r1/1w</id>
+ <inline>0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b</inline>
+ <!-- 3059301306072a8648ce3d020106082a8648ce3d0301070342000431028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f116744743a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b -->
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 106</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256r1/2s</id>
+ <inline>0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632533</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 107</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256r1/2w</id>
+ <inline>0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b</inline>
+ <!-- 3059301306072a8648ce3d020106082a8648ce3d0301070342000431028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f116744743a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b -->
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 107</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256r1/3s</id>
+ <inline>0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632543</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 108</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256r1/3w</id>
+ <inline>0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b</inline>
+ <!-- 3059301306072a8648ce3d020106082a8648ce3d0301070342000431028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f116744743a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b -->
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 108</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256r1/4s</id>
+ <inline>0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254b</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 109</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256r1/4w</id>
+ <inline>0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b</inline>
+ <!-- 3059301306072a8648ce3d020106082a8648ce3d0301070342000431028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f116744743a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b -->
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 109</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256r1/5s</id>
+ <inline>0x0ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 111</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256r1/5w</id>
+ <inline>0x31028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f1167447,0x43a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b</inline>
+ <!-- 3059301306072a8648ce3d020106082a8648ce3d0301070342000431028f3377fc8f2b1967edaab90213acad0da9f50897f08f57537f78f116744743a1930189363bbde2ac4cbd1649cdc6f451add71dd2f16a8a867f2b17caa16b -->
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 111</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp384r1/1s</id>
+ <inline>0x0ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52959</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>tcId = 192</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp384r1/1w</id>
+ <inline>0xe9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c0,0x20156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e</inline>
+ <!-- 3076301006072a8648ce3d020106052b8104002203620004e9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c020156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e -->
+ <curve>secg/secp384r1</curve>
+ <desc>tcId = 192</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp384r1/2s</id>
+ <inline>0x0ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52969</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>tcId = 193</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp384r1/2w</id>
+ <inline>0xe9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c0,0x20156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e</inline>
+ <!-- 3076301006072a8648ce3d020106052b8104002203620004e9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c020156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e -->
+ <curve>secg/secp384r1</curve>
+ <desc>tcId = 193</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp384r1/3s</id>
+ <inline>0x0ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52971</inline>
+ <curve>secg/secp384r1</curve>
+ <desc>tcId = 195</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp384r1/3w</id>
+ <inline>0xe9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c0,0x20156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e</inline>
+ <!-- 3076301006072a8648ce3d020106052b8104002203620004e9dfaaab808b3aac1ccca7cc6242a7ee583249afe8ee8f66b904cc8eec34ad334456e00f33a94de8b5169cf0199550c020156e9651734ff999c5f3ea62b83d0083a6093f234457251ecf72c41e4df7cea2420b5454a7f690034380bac981e92e -->
+ <curve>secg/secp384r1</curve>
+ <desc>tcId = 195</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp521r1/1s</id>
+ <inline>0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e9138631b</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 273</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp521r1/1w</id>
+ <inline>0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314</inline>
+ <!-- 30819b301006072a8648ce3d020106052b81040023038186000401ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b900854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 -->
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 273</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp521r1/2s</id>
+ <inline>0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e9138639b</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 274</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp521r1/2w</id>
+ <inline>0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314</inline>
+ <!-- 30819b301006072a8648ce3d020106052b81040023038186000401ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b900854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 -->
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 274</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp521r1/3s</id>
+ <inline>0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e913863db</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 275</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp521r1/3w</id>
+ <inline>0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314</inline>
+ <!-- 30819b301006072a8648ce3d020106052b81040023038186000401ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b900854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 -->
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 275</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp521r1/4s</id>
+ <inline>0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e913863fb</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 276</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp521r1/4w</id>
+ <inline>0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314</inline>
+ <!-- 30819b301006072a8648ce3d020106052b81040023038186000401ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b900854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 -->
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 276</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp521r1/5s</id>
+ <inline>0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386403</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 277</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp521r1/5w</id>
+ <inline>0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314</inline>
+ <!-- 30819b301006072a8648ce3d020106052b81040023038186000401ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b900854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 -->
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 277</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp521r1/6s</id>
+ <inline>0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386407</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 279</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp521r1/6w</id>
+ <inline>0x01ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b9,0x00854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314</inline>
+ <!-- 30819b301006072a8648ce3d020106052b81040023038186000401ad5043591dbe81657fe3d1c3d7a516606ad9d320a35fce8aaec8a950fb53f95388f3fc48be998e99334ad9e9234cded14471fe86caccaa07d058ee8771733ac3b900854de36366590b9ee4d0370ea6b00f7ebd8156ccf14e99f1a5344a9b4964fbb8348b081a8840c6b64be77997ad8bebfea5e7d9f7a6a7fa6d7655c50b2b7835f314 -->
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 279</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256k1/1s</id>
+ <inline>0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c3</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 362</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256k1/1w</id>
+ <inline>0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b</inline>
+ <!-- 3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b -->
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 362</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256k1/2s</id>
+ <inline>0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364103</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 363</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256k1/2w</id>
+ <inline>0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b</inline>
+ <!-- 3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b -->
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 363</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256k1/3s</id>
+ <inline>0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364123</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 364</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256k1/3w</id>
+ <inline>0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b</inline>
+ <!-- 3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b -->
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 364</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256k1/4s</id>
+ <inline>0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364133</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 365</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256k1/4w</id>
+ <inline>0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b</inline>
+ <!-- 3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b -->
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 365</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256k1/5s</id>
+ <inline>0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413b</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 366</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256k1/5w</id>
+ <inline>0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b</inline>
+ <!-- 3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b -->
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 366</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/secp256k1/6s</id>
+ <inline>0x0fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f</inline>
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 368</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/secp256k1/6w</id>
+ <inline>0x32bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e,0x981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b</inline>
+ <!-- 3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b -->
+ <curve>secg/secp256k1</curve>
+ <desc>tcId = 368</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP224r1/1s</id>
+ <inline>0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a792dd</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>tcId = 441</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP224r1/1w</id>
+ <inline>0xaaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d126,0x8c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66</inline>
+ <!-- 3052301406072a8648ce3d020106092b2403030208010105033a0004aaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d1268c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66 -->
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>tcId = 441</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP224r1/2s</id>
+ <inline>0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7935d</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>tcId = 442</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP224r1/2w</id>
+ <inline>0xaaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d126,0x8c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66</inline>
+ <!-- 3052301406072a8648ce3d020106092b2403030208010105033a0004aaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d1268c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66 -->
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>tcId = 442</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP224r1/3s</id>
+ <inline>0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939d</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>tcId = 444</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP224r1/3w</id>
+ <inline>0xaaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d126,0x8c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66</inline>
+ <!-- 3052301406072a8648ce3d020106092b2403030208010105033a0004aaf040d6cad2c18b953de46420b387fa83474d74c6767ed708b9d1268c82a09310bc35b5caf2d9b46318b895e4c097ed501d2dcb14d30a66 -->
+ <curve>brainpool/brainpoolP224r1</curve>
+ <desc>tcId = 444</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP256r1/1s</id>
+ <inline>0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974855f5</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>tcId = 524</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP256r1/1w</id>
+ <inline>0xa4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b3,0x77d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b</inline>
+ <!-- 305a301406072a8648ce3d020106092b240303020801010703420004a4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b377d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b -->
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>tcId = 524</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP256r1/2s</id>
+ <inline>0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e8297485675</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>tcId = 525</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP256r1/2w</id>
+ <inline>0xa4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b3,0x77d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b</inline>
+ <!-- 305a301406072a8648ce3d020106092b240303020801010703420004a4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b377d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b -->
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>tcId = 525</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP256r1/3s</id>
+ <inline>0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e8297485695</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>tcId = 526</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP256r1/3w</id>
+ <inline>0xa4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b3,0x77d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b</inline>
+ <!-- 305a301406072a8648ce3d020106092b240303020801010703420004a4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b377d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b -->
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>tcId = 526</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP256r1/4s</id>
+ <inline>0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a5</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>tcId = 528</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP256r1/4w</id>
+ <inline>0xa4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b3,0x77d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b</inline>
+ <!-- 305a301406072a8648ce3d020106092b240303020801010703420004a4597cfee2797aaace662caa92a444592c9f626f04beca98a06b6dfcaf53f4b377d67b1c109154309bcf3d2f3928e58747806f08a8cf88436ac1b2110b83493b -->
+ <curve>brainpool/brainpoolP256r1</curve>
+ <desc>tcId = 528</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320r1/1s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59233</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 604</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320r1/1w</id>
+ <inline>0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d</inline>
+ <!-- 306a301406072a8648ce3d020106092b2403030208010109035200044e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfed230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d -->
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 604</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320r1/2s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c592b3</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 605</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320r1/2w</id>
+ <inline>0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d</inline>
+ <!-- 306a301406072a8648ce3d020106092b2403030208010109035200044e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfed230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d -->
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 605</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320r1/3s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c592f3</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 606</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320r1/3w</id>
+ <inline>0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d</inline>
+ <!-- 306a301406072a8648ce3d020106092b2403030208010109035200044e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfed230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d -->
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 606</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320r1/4s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59303</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 607</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320r1/4w</id>
+ <inline>0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d</inline>
+ <!-- 306a301406072a8648ce3d020106092b2403030208010109035200044e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfed230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d -->
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 607</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320r1/5s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c5930b</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 608</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320r1/5w</id>
+ <inline>0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d</inline>
+ <!-- 306a301406072a8648ce3d020106092b2403030208010109035200044e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfed230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d -->
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 608</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320r1/6s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c5930f</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 610</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320r1/6w</id>
+ <inline>0x4e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfe,0xd230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d</inline>
+ <!-- 306a301406072a8648ce3d020106092b2403030208010109035200044e73d59ec474e679414d0922de22e06d0dad990ba4746c3d026bdea52e7bbeaac928d0ddaab29dfed230dde60fd57d4ef8e935b23cb7d4216b278b17a3f02d70454fa0e45da2054b91b0c4b663ab243d -->
+ <curve>brainpool/brainpoolP320r1</curve>
+ <desc>tcId = 610</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP384r1/1s</id>
+ <inline>0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904652f</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>tcId = 684</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP384r1/1w</id>
+ <inline>0x09d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf,0x03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf</inline>
+ <!-- 307a301406072a8648ce3d020106092b240303020801010b0362000409d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf -->
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>tcId = 684</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP384r1/2s</id>
+ <inline>0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904654f</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>tcId = 685</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP384r1/2w</id>
+ <inline>0x09d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf,0x03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf</inline>
+ <!-- 307a301406072a8648ce3d020106092b240303020801010b0362000409d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf -->
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>tcId = 685</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP384r1/3s</id>
+ <inline>0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904655f</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>tcId = 686</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP384r1/3w</id>
+ <inline>0x09d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf,0x03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf</inline>
+ <!-- 307a301406072a8648ce3d020106092b240303020801010b0362000409d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf -->
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>tcId = 686</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP384r1/4s</id>
+ <inline>0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046563</inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>tcId = 688</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP384r1/4w</id>
+ <inline>0x09d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf,0x03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf</inline>
+ <!-- 307a301406072a8648ce3d020106092b240303020801010b0362000409d897b6d1452a2f91c4c37fbb06d82f9ebf722298cafb135e582cded3e3210033e4cd07703c34acf36ba72b401c30bf03b161af6e11309a1122145c431996047a7e7808cf8314b6ec37c61a817d08c7d00c8c7b5d258f2674378c832f682edf -->
+ <curve>brainpool/brainpoolP384r1</curve>
+ <desc>tcId = 688</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP512r1/1s</id>
+ <inline>0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca9003b</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>tcId = 774</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP512r1/1w</id>
+ <inline>0x2ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc,0x99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd</inline>
+ <!-- 30819b301406072a8648ce3d020106092b240303020801010d03818200042ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd -->
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>tcId = 774</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP512r1/2s</id>
+ <inline>0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca9005b</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>tcId = 775</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP512r1/2w</id>
+ <inline>0x2ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc,0x99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd</inline>
+ <!-- 30819b301406072a8648ce3d020106092b240303020801010d03818200042ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd -->
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>tcId = 775</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP512r1/3s</id>
+ <inline>0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90063</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>tcId = 776</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP512r1/3w</id>
+ <inline>0x2ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc,0x99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd</inline>
+ <!-- 30819b301406072a8648ce3d020106092b240303020801010d03818200042ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd -->
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>tcId = 776</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP512r1/4s</id>
+ <inline>0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90067</inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>tcId = 778</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP512r1/4w</id>
+ <inline>0x2ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc,0x99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd</inline>
+ <!-- 30819b301406072a8648ce3d020106092b240303020801010d03818200042ee402777200a1c9e7eceb61feb070af49429f9240d7c0bab9b2f01c5ee145683df47cbe852ff6f99198f6fdfaef1925eb96bd25e03d6d70f709eb1922308acc99a3fbc1e982db7a7b3bbf7827ea70912ee677bb0ba70bfabec38d4b993af165c40727680fe79ad0fbb55d1e9568d978b11f77cc4e72aa7ca5c391034078b8bd -->
+ <curve>brainpool/brainpoolP512r1</curve>
+ <desc>tcId = 778</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP224t1/1s</id>
+ <inline>0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a792dd</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>tcId = 854</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP224t1/1w</id>
+ <inline>0x1b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c2,0x6709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1</inline>
+ <!-- 3052301406072a8648ce3d020106092b2403030208010106033a00041b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c26709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1 -->
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>tcId = 854</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP224t1/2s</id>
+ <inline>0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7935d</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>tcId = 855</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP224t1/2w</id>
+ <inline>0x1b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c2,0x6709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1</inline>
+ <!-- 3052301406072a8648ce3d020106092b2403030208010106033a00041b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c26709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1 -->
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>tcId = 855</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP224t1/3s</id>
+ <inline>0x0d7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939d</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>tcId = 857</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP224t1/3w</id>
+ <inline>0x1b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c2,0x6709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1</inline>
+ <!-- 3052301406072a8648ce3d020106092b2403030208010106033a00041b801b9b969daaddbc40876ef79201c5dd8e480f003a043e818862c26709e1b2f6d8826ae4257a5db46b78848091c56a54577248185936b1 -->
+ <curve>brainpool/brainpoolP224t1</curve>
+ <desc>tcId = 857</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP256t1/1s</id>
+ <inline>0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974855f5</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>tcId = 935</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP256t1/1w</id>
+ <inline>0x2053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b,0x02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245</inline>
+ <!-- 305a301406072a8648ce3d020106092b2403030208010108034200042053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245 -->
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>tcId = 935</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP256t1/2s</id>
+ <inline>0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e8297485675</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>tcId = 936</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP256t1/2w</id>
+ <inline>0x2053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b,0x02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245</inline>
+ <!-- 305a301406072a8648ce3d020106092b2403030208010108034200042053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245 -->
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>tcId = 936</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP256t1/3s</id>
+ <inline>0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e8297485695</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>tcId = 937</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP256t1/3w</id>
+ <inline>0x2053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b,0x02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245</inline>
+ <!-- 305a301406072a8648ce3d020106092b2403030208010108034200042053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245 -->
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>tcId = 937</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP256t1/4s</id>
+ <inline>0x0a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a5</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>tcId = 939</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP256t1/4w</id>
+ <inline>0x2053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b,0x02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245</inline>
+ <!-- 305a301406072a8648ce3d020106092b2403030208010108034200042053bf936c82599d38aef8ec650f502ad9dce3be818d32de66009a3137604f5b02317c894b1138b873b612714c95527021b4240edd45ad26ee96d507954c3245 -->
+ <curve>brainpool/brainpoolP256t1</curve>
+ <desc>tcId = 939</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320t1/1s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59233</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1015</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320t1/1w</id>
+ <inline>0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd</inline>
+ <!-- 306a301406072a8648ce3d020106092b240303020801010a03520004aac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b972253955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd -->
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1015</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320t1/2s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c592b3</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1016</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320t1/2w</id>
+ <inline>0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd</inline>
+ <!-- 306a301406072a8648ce3d020106092b240303020801010a03520004aac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b972253955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd -->
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1016</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320t1/3s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c592f3</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1017</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320t1/3w</id>
+ <inline>0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd</inline>
+ <!-- 306a301406072a8648ce3d020106092b240303020801010a03520004aac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b972253955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd -->
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1017</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320t1/4s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c59303</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1018</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320t1/4w</id>
+ <inline>0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd</inline>
+ <!-- 306a301406072a8648ce3d020106092b240303020801010a03520004aac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b972253955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd -->
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1018</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320t1/5s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c5930b</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1019</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320t1/5w</id>
+ <inline>0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd</inline>
+ <!-- 306a301406072a8648ce3d020106092b240303020801010a03520004aac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b972253955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd -->
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1019</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP320t1/6s</id>
+ <inline>0x0d35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e98691555b44c5930f</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1021</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP320t1/6w</id>
+ <inline>0xaac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b97225,0x3955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd</inline>
+ <!-- 306a301406072a8648ce3d020106092b240303020801010a03520004aac3566c8e494d7d52976b107a9b9058e65e541c01dab5d4bba90658a655890fd2c48d29f0b972253955fdbd31c6328df2e893fe5b401ddc529c4ed70a9c46badb80843277b8f9874538312460d54dfd -->
+ <curve>brainpool/brainpoolP320t1</curve>
+ <desc>tcId = 1021</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP384t1/1s</id>
+ <inline>0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904652f</inline>
+ <curve>brainpool/brainpoolP384t1</curve>
+ <desc>tcId = 1093</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP384t1/1w</id>
+ <inline>0x1e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf,0x88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71</inline>
+ <!-- 307a301406072a8648ce3d020106092b240303020801010c036200041e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71 -->
+ <curve>brainpool/brainpoolP384t1</curve>
+ <desc>tcId = 1093</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP384t1/2s</id>
+ <inline>0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904654f</inline>
+ <curve>brainpool/brainpoolP384t1</curve>
+ <desc>tcId = 1094</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP384t1/2w</id>
+ <inline>0x1e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf,0x88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71</inline>
+ <!-- 307a301406072a8648ce3d020106092b240303020801010c036200041e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71 -->
+ <curve>brainpool/brainpoolP384t1</curve>
+ <desc>tcId = 1094</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP384t1/3s</id>
+ <inline>0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e904655f</inline>
+ <curve>brainpool/brainpoolP384t1</curve>
+ <desc>tcId = 1095</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP384t1/3w</id>
+ <inline>0x1e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf,0x88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71</inline>
+ <!-- 307a301406072a8648ce3d020106092b240303020801010c036200041e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71 -->
+ <curve>brainpool/brainpoolP384t1</curve>
+ <desc>tcId = 1095</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP384t1/4s</id>
+ <inline>0x08cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046563</inline>
+ <curve>brainpool/brainpoolP384t1</curve>
+ <desc>tcId = 1097</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP384t1/4w</id>
+ <inline>0x1e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf,0x88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71</inline>
+ <!-- 307a301406072a8648ce3d020106092b240303020801010c036200041e6c405358fab0f63c09eddacc372dd29c17d0eebcffe37975ee3c6bf05c7b8db09f104fcf6cc1a0576c44c12637b4bf88938d33d2d9390c1075f3af467937074db4022a44e2ea2e9cbff6bfcb4af4909fbb8bd3ab627e1dd1649d5faec28a71 -->
+ <curve>brainpool/brainpoolP384t1</curve>
+ <desc>tcId = 1097</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP512t1/1s</id>
+ <inline>0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca9003b</inline>
+ <curve>brainpool/brainpoolP512t1</curve>
+ <desc>tcId = 1185</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP512t1/1w</id>
+ <inline>0x242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd079,0x3d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed</inline>
+ <!-- 30819b301406072a8648ce3d020106092b240303020801010e0381820004242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd0793d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed -->
+ <curve>brainpool/brainpoolP512t1</curve>
+ <desc>tcId = 1185</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP512t1/2s</id>
+ <inline>0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca9005b</inline>
+ <curve>brainpool/brainpoolP512t1</curve>
+ <desc>tcId = 1186</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP512t1/2w</id>
+ <inline>0x242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd079,0x3d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed</inline>
+ <!-- 30819b301406072a8648ce3d020106092b240303020801010e0381820004242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd0793d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed -->
+ <curve>brainpool/brainpoolP512t1</curve>
+ <desc>tcId = 1186</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP512t1/3s</id>
+ <inline>0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90063</inline>
+ <curve>brainpool/brainpoolP512t1</curve>
+ <desc>tcId = 1187</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP512t1/3w</id>
+ <inline>0x242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd079,0x3d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed</inline>
+ <!-- 30819b301406072a8648ce3d020106092b240303020801010e0381820004242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd0793d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed -->
+ <curve>brainpool/brainpoolP512t1</curve>
+ <desc>tcId = 1187</desc>
+ </pubkey>
+ <privkey>
+ <id>addsub/brainpoolP512t1/4s</id>
+ <inline>0x0aadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90067</inline>
+ <curve>brainpool/brainpoolP512t1</curve>
+ <desc>tcId = 1189</desc>
+ </privkey>
+ <pubkey>
+ <id>addsub/brainpoolP512t1/4w</id>
+ <inline>0x242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd079,0x3d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed</inline>
+ <!-- 30819b301406072a8648ce3d020106092b240303020801010e0381820004242748b1fa44edac413a79ee1cdcc3d4bab5fa125d4d692208ac52764377b84fe3472dbe8f292572f1f3dbf3e927624d983d5c0f4bfca5224dc0739889ddd0793d1f2089639992a74a3c1783d2f1bd50f85ad77540adfa78b1a6581bcd74b3ef0dd996be2809ed16434c42b3a29cb81b1a39720cede1b640f018788afa61cbed -->
+ <curve>brainpool/brainpoolP512t1</curve>
+ <desc>tcId = 1189</desc>
+ </pubkey>
+
+ <!-- CVE-2017-8932 tests -->
+ <privkey>
+ <id>cve_2017_8932/secp256r1/1s</id>
+ <inline>0x2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 112</desc>
+ </privkey>
+ <pubkey>
+ <id>cve_2017_8932/secp256r1/1w</id>
+ <inline>0x023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882ea,0xf93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad</inline>
+ <!-- 3059301306072a8648ce3d020106082a8648ce3d03010703420004023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882eaf93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad -->
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 112</desc>
+ </pubkey>
+ <privkey>
+ <id>cve_2017_8932/secp256r1/2s</id>
+ <inline>0x313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd</inline>
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 113</desc>
+ </privkey>
+ <pubkey>
+ <id>cve_2017_8932/secp256r1/2w</id>
+ <inline>0xcc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06,0xa2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031</inline>
+ <!-- 3059301306072a8648ce3d020106082a8648ce3d03010703420004cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031 -->
+ <curve>secg/secp256r1</curve>
+ <desc>tcId = 113</desc>
+ </pubkey>
+
+ <!-- CVE-2017-10176 tests -->
+ <privkey>
+ <id>cve_2017_10176/secp521r1/1s</id>
+ <inline>0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e913863f7</inline>
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 280</desc>
+ </privkey>
+ <pubkey>
+ <id>cve_2017_10176/secp521r1/1w</id>
+ <inline>0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66,0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650</inline>
+ <!-- 30819b301006072a8648ce3d020106052b81040023038186000400c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650 -->
+ <curve>secg/secp521r1</curve>
+ <desc>tcId = 280</desc>
+ </pubkey>
+</keys> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/data/wycheproof/results.xml b/src/cz/crcs/ectester/data/wycheproof/results.xml
new file mode 100644
index 0000000..5508f4c
--- /dev/null
+++ b/src/cz/crcs/ectester/data/wycheproof/results.xml
@@ -0,0 +1,589 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../schema.xsd">
+ <result>
+ <id>addsub/secp224r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x475fd96e0eb8cb8f100a5d7fe043a7a6851d1d611da2643a3c6ae708</inline>
+ <curve>secg/secp224r1</curve>
+ <onekey>wycheproof/addsub/secp224r1/1s</onekey>
+ <otherkey>wycheproof/addsub/secp224r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp224r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x41ef931d669d1f57d8bb95a01a92321da74be8c6cbc3bbe0b2e73ebd</inline>
+ <curve>secg/secp224r1</curve>
+ <onekey>wycheproof/addsub/secp224r1/2s</onekey>
+ <otherkey>wycheproof/addsub/secp224r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp224r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x11ff15126411299cbd49e2b7542e69e91ef132e2551a16ecfebb23a3</inline>
+ <curve>secg/secp224r1</curve>
+ <onekey>wycheproof/addsub/secp224r1/3s</onekey>
+ <otherkey>wycheproof/addsub/secp224r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xf7407d61fdf581be4f564621d590ca9b7ba37f31396150f9922f1501da8c83ef</inline>
+ <curve>secg/secp256r1</curve>
+ <onekey>wycheproof/addsub/secp256r1/1s</onekey>
+ <otherkey>wycheproof/addsub/secp256r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x82236fd272208693e0574555ca465c6cc512163486084fa57f5e1bd2e2ccc0b3</inline>
+ <curve>secg/secp256r1</curve>
+ <onekey>wycheproof/addsub/secp256r1/2s</onekey>
+ <otherkey>wycheproof/addsub/secp256r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x06537149664dba1a9924654cb7f787ed224851b0df25ef53fcf54f8f26cd5f3f</inline>
+ <curve>secg/secp256r1</curve>
+ <onekey>wycheproof/addsub/secp256r1/3s</onekey>
+ <otherkey>wycheproof/addsub/secp256r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256r1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xf2b38539bce995d443c7bfeeefadc9e42cc2c89c60bf4e86eac95d51987bd112</inline>
+ <curve>secg/secp256r1</curve>
+ <onekey>wycheproof/addsub/secp256r1/4s</onekey>
+ <otherkey>wycheproof/addsub/secp256r1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256r1/5test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x027b013a6f166db655d69d643c127ef8ace175311e667dff2520f5b5c75b7659</inline>
+ <curve>secg/secp256r1</curve>
+ <onekey>wycheproof/addsub/secp256r1/5s</onekey>
+ <otherkey>wycheproof/addsub/secp256r1/5w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp384r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x2ecf9dc47e8b07ae61ddbd1680ead02698e9e8469f78d5a28328e48d0c9d7a2ac787e50cba58cc44a32fb1235d2d7027
+ </inline>
+ <curve>secg/secp384r1</curve>
+ <onekey>wycheproof/addsub/secp384r1/1s</onekey>
+ <otherkey>wycheproof/addsub/secp384r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp384r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x06ee9f55079d3d3c18c683ba33e0d2521be97c4fbf7917bf3b6287d58ffcde2df88842e3f5530b39549ac20974b1b60e
+ </inline>
+ <curve>secg/secp384r1</curve>
+ <onekey>wycheproof/addsub/secp384r1/2s</onekey>
+ <otherkey>wycheproof/addsub/secp384r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp384r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x024c5281487216058270cd1cfe259e948310e4adc263a9edaa4da0bc3f5f8ce8ffc88ae41b2c050bf6dd9c8c66857237
+ </inline>
+ <curve>secg/secp384r1</curve>
+ <onekey>wycheproof/addsub/secp384r1/3s</onekey>
+ <otherkey>wycheproof/addsub/secp384r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp521r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x00286cefaaf38ca4c6657eb9b187d8614d51775fd71c1a79b4c0ef1a0d4ce72b6f5b2bc854a4e78283530942a3f4fd2a8586d5ea51513c89d3d29de5de06321e118e
+ </inline>
+ <curve>secg/secp521r1</curve>
+ <onekey>wycheproof/addsub/secp521r1/1s</onekey>
+ <otherkey>wycheproof/addsub/secp521r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp521r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x014790de14c481f1336fcb7d33a8bf8e23eb594cc48608e9edfe0e326e106b67e7eaa3f04ec9985599178f632a5ee6419e11217060e9fcd5958a43882bf8cd3be6ba
+ </inline>
+ <curve>secg/secp521r1</curve>
+ <onekey>wycheproof/addsub/secp521r1/2s</onekey>
+ <otherkey>wycheproof/addsub/secp521r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp521r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x01ae775dbc4096a3aea7977b1a0af4b2830ecf9ca927a6247fba4cccb46b3f71d0e7abb8dda72d1c1ee7bb5b875b4773cc8df40f732819c4147da330775d1742ea35
+ </inline>
+ <curve>secg/secp521r1</curve>
+ <onekey>wycheproof/addsub/secp521r1/3s</onekey>
+ <otherkey>wycheproof/addsub/secp521r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp521r1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x01979fb05e068a12a3f20cfdfb9eaee9f22b356edcc7655383ed38124b86814f86a6f2216a34f3fc2299d403ee42408f95d08c5c6cd11db72cbf299a4a3c2545be25
+ </inline>
+ <curve>secg/secp521r1</curve>
+ <onekey>wycheproof/addsub/secp521r1/4s</onekey>
+ <otherkey>wycheproof/addsub/secp521r1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp521r1/5test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x0197ebe26798bf67f06ff0282773af75115531f41d94c093d87481b76bef707bc222f2d6672f84a00fa20c5ed27027ab4006b68d93ee2151016c9ddbe014346272e2
+ </inline>
+ <curve>secg/secp521r1</curve>
+ <onekey>wycheproof/addsub/secp521r1/5s</onekey>
+ <otherkey>wycheproof/addsub/secp521r1/5w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp521r1/6test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x01c168314cdc85757ade34a52a9e5379ffa5968f084b7e404939a8033a0fc698e26211754b9b2c04cf8a1420abe6e986ef1a238bbb91dd402b72e0ed50a876f1a83e
+ </inline>
+ <curve>secg/secp521r1</curve>
+ <onekey>wycheproof/addsub/secp521r1/6s</onekey>
+ <otherkey>wycheproof/addsub/secp521r1/6w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256k1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x09c7337df6c2b35edf3a21382511cc5add1a71a84cbf8d3396a5be548d92fa67</inline>
+ <curve>secg/secp256k1</curve>
+ <onekey>wycheproof/addsub/secp256k1/1s</onekey>
+ <otherkey>wycheproof/addsub/secp256k1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256k1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xd16caedd25793666f9e26f5331382106f54095b3d20d40c745b68ca76c0e6983</inline>
+ <curve>secg/secp256k1</curve>
+ <onekey>wycheproof/addsub/secp256k1/2s</onekey>
+ <otherkey>wycheproof/addsub/secp256k1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256k1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xb8ae1e21d8b34ce4caffed7167a26868ec80a7d4a6a98b639d4d05cd226504de</inline>
+ <curve>secg/secp256k1</curve>
+ <onekey>wycheproof/addsub/secp256k1/3s</onekey>
+ <otherkey>wycheproof/addsub/secp256k1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256k1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x02776315fe147a36a4b0987492b6503acdea60f926450e5eddb9f88fc82178d3</inline>
+ <curve>secg/secp256k1</curve>
+ <onekey>wycheproof/addsub/secp256k1/4s</onekey>
+ <otherkey>wycheproof/addsub/secp256k1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256k1/5test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x3988c9c7050a28794934e5bd67629b556d97a4858d22812835f4a37dca351943</inline>
+ <curve>secg/secp256k1</curve>
+ <onekey>wycheproof/addsub/secp256k1/5s</onekey>
+ <otherkey>wycheproof/addsub/secp256k1/5w</otherkey>
+ </result>
+ <result>
+ <id>addsub/secp256k1/6test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x4b52257d8b3ba387797fdf7a752f195ddc4f7d76263de61d0d52a5ec14a36cbf</inline>
+ <curve>secg/secp256k1</curve>
+ <onekey>wycheproof/addsub/secp256k1/6s</onekey>
+ <otherkey>wycheproof/addsub/secp256k1/6w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP224r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x1be0d59d1f0f3a743ae19c5246099391098f71444223831e16cfa0c5</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP224r1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP224r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP224r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x7e00a9267243cea4ba7617860b6fcf404e0357d1202d8c85dc5e07d3</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP224r1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP224r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP224r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xaac6a805f4ce1b6dcc13ec4ed16a889dc4d708f7f6f1e23471338324</inline>
+ <curve>brainpool/brainpoolP224r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP224r1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP224r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP256r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x1950b7ce510d4d8648e80c6385a42d005433fc5ca61e2022a1405fe18142c246</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP256r1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP256r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP256r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x5c05c4d877a0e2af5ffa004c122630bb87157cf346dbeb8ae13017162da208f4</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP256r1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP256r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP256r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x9639bbd4e22194ce3892a814c82eddbd21dde05cfac20e99396e3d6ef0841f7c</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP256r1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP256r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP256r1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x341cbdf61f9dd620ba6873a74804afe30a06b0a113a6916a4104d2d4cc196aec</inline>
+ <curve>brainpool/brainpoolP256r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP256r1/4s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP256r1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xc0038da858441f559a864dcd6c4558437f9ad091a67c3fda69a9e0cb6f446a8b47ae95edc2f4eade</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320r1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x8258131a80bc9f2b8ba532ef1253ef39dce25e6deb85227c670273521c311dbb9bf1a56dd29107b3</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320r1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xae752e75684a9adfc6198e6c1ce9249d26743104e8b0bd0417998c62982622ea2fdf6917413d547c</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320r1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320r1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x37bfbb637fce27ee80b3af326546303e0bd8af01b72f591830a548609055bda489d9a4e6b5e3f43e</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320r1/4s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320r1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320r1/5test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x854ce9516e73c6cc8d0d6ce3cdf933541a719578712440f02a86829af1398fcab2bb0949c1d63106</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320r1/5s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320r1/5w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320r1/6test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x7dfd07c1cfe70db4772cf9f6bb6b58a10bbc9509e5ce86651d5c395f3544f62d6d8f8109edba441a</inline>
+ <curve>brainpool/brainpoolP320r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320r1/6s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320r1/6w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP384r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x3729bcd215b41c658b832686c81362b3485d75b09478c6dde3b5e278564ef4162bdd6ff65afc6e8213bba9b6c54ba1eb
+ </inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP384r1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP384r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP384r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x12ba4622daf1f2f950aad6d54aaab821885a47a98573afea49bc1896041ee9501acef82810f3755ff284e16665bd0f62
+ </inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP384r1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP384r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP384r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x7fb5398519857f2c17cddd0a9d2c1660ac35b4723e4a049ba5c58c458b742dfa813a5c7175e1c0974b514bfaeb0039f8
+ </inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP384r1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP384r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP384r1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x0f0a1d20ba6a7b2c48154b43870be4890979d9261950736de96c29f371233b1ef94a79c2ab698868f00cea7e912deb94
+ </inline>
+ <curve>brainpool/brainpoolP384r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP384r1/4s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP384r1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP512r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x194871645bbfc309eba92c5613ca7c6aa566fdab45635f656148ec7122d71c825f36852f52722ea949c2572dbb6b894a21f96a05c9bee0df6c6b4faa3197079a
+ </inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP512r1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP512r1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP512r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x3a6e57858d4e61c7ed2cb93c124221210293a345b47f7644910543ac03117f48b0343ddebd2cf9925e3dc5e1ea590739ed2c2372e1146f84fd262ac7d8eebacd
+ </inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP512r1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP512r1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP512r1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x8e0a186a51eae08a86fdd476bcfd961d02be74966ce3c2d937c808db518f2ddc4760bfc924af72f85eb188ebc70edde6d12f402735f58b9006f8b8e283ef9fbe
+ </inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP512r1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP512r1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP512r1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x300b1d80d9dc5587076b7d850ccd00cf8961f389c4ded60bf910d98f196f67c3839d2197101607612b335871a818d50d8f4bb6163cc839cf41af0b742c7254f4
+ </inline>
+ <curve>brainpool/brainpoolP512r1</curve>
+ <onekey>wycheproof/addsub/brainpoolP512r1/4s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP512r1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP224t1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x97ded4c2e06b5a13c9109be3fa42dc2ca93a306fdf9e85ac4bb02e22</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP224t1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP224t1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP224t1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x686798270c7e188e6ab3e28a10754f965d5d02f33d30d8faf38155f4</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP224t1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP224t1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP224t1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xd64f68debaf751d63da1883668822031c69e913cc53b969e5fbae845</inline>
+ <curve>brainpool/brainpoolP224t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP224t1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP224t1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP256t1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x4875ed4b2bc7e7a0cb89d93b359fa72ddaf0377ddeddd33f62ec2450cd80e7cd</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP256t1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP256t1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP256t1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x315637f94d6776cc3928c1ffbe3c7004aa70b787cc0687faee1da5f9324a36c4</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP256t1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP256t1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP256t1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x54d1009ab7d3cb9d4314ea7512f7bc4d916ecd47bc9e491ad4a6d65a40672554</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP256t1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP256t1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP256t1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x892923527eb529de963e902641c01701a66cd999d1b665717d7b11cbb5a96f7c</inline>
+ <curve>brainpool/brainpoolP256t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP256t1/4s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP256t1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320t1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x147c9b3b4880f7f6d4eb96f891672cb0d09a6bef15574ab2a43f09ae7f8090cdfa81517e098dac1e</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320t1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320t1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320t1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x47f4412278edc51ba0635853a82e033b164a68194d4c3e2492017432daaa8c35684c343f701f6b02</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320t1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320t1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320t1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xa64c2b075abf446a9ba43f6ffcefda795835ab2e1c4d19bd9c9ede59cd9eaf9c831a520b1e0ce269</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320t1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320t1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320t1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xb3b25821ac9b07c614f6fce7f9a1c2325d3cbd51cac82dadeb79037a23bce03b0352407ccd447af8</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320t1/4s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320t1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320t1/5test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x594aebd8010757d15f79631af0e481310359e0086e4e988ab5525a9303aaf800cd4ef123ceb68875</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320t1/5s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320t1/5w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP320t1/6test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0xc7e67dc2f64d0e66841777a6f014340b8a63f42024c6cd5ac5e10cec3b02a2d050c2fd8f078a754f</inline>
+ <curve>brainpool/brainpoolP320t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP320t1/6s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP320t1/6w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP384t1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x22d772bd2104c3d24b8505b3e7d1f3f00ca2dacb493ca729170854ef2158407a0ffab006153d5cb7781e9cb57cda505f
+ </inline>
+ <curve>brainpool/brainpoolP384t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP384t1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP384t1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP384t1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x2b2c617f8c84713f8440e5e273341d69edf9e6ea2056af38ccfc6ee733a9c11e1f9aa63cb3615d2b3cebe69d8360a2bd
+ </inline>
+ <curve>brainpool/brainpoolP384t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP384t1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP384t1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP384t1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x28518f75e020e00095d47166f7825f1767b6425172decde390c9266764c8b631608dc323b8415c39c9d0b8a24cd337ac
+ </inline>
+ <curve>brainpool/brainpoolP384t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP384t1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP384t1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP384t1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x4424a1b48eba0524e4aa82455e282b35cf0d13d8536fe6c410cd5050f3d4d1739254945a8f580d43ee0245b1df67de56
+ </inline>
+ <curve>brainpool/brainpoolP384t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP384t1/4s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP384t1/4w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP512t1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x71f9265fcb0a1a899c5a3c8dc31d2fc3c87955285687e73928aab9c5cc750a83760292d514d4cde457fc8e05bb49eac1fb677ffa5f9dc9fa62e1126a9eded5a4
+ </inline>
+ <curve>brainpool/brainpoolP512t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP512t1/1s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP512t1/1w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP512t1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x79cc52b05b942dec984ea1d88675fcff93f87103b58bd0f7153c7b36b205ea39f99e85017e97ba89726d15e7d7fe5eb1525827011b3852e1121753dea15cfbb9
+ </inline>
+ <curve>brainpool/brainpoolP512t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP512t1/2s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP512t1/2w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP512t1/3test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x618f57d971efa605cb141993a1149dff87d01c773fb8f2a8db5726eb1703522568cc55abca616dae5727f390c90cfa792d4349856820f2d0b5df7da418328e7f
+ </inline>
+ <curve>brainpool/brainpoolP512t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP512t1/3s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP512t1/3w</otherkey>
+ </result>
+ <result>
+ <id>addsub/brainpoolP512t1/4test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x34998a162b0463d81a96dda6c4e256b94ed35f89cb0b69a9af70123bec61b387bb358451e1994d6c29acbec66c50c61f36b66da33782db21521415952b55fa48
+ </inline>
+ <curve>brainpool/brainpoolP512t1</curve>
+ <onekey>wycheproof/addsub/brainpoolP512t1/4s</onekey>
+ <otherkey>wycheproof/addsub/brainpoolP512t1/4w</otherkey>
+ </result>
+ <result>
+ <id>cve_2017_10176/secp521r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>
+ 0x01bc33425e72a12779eacb2edcc5b63d1281f7e86dbc7bf99a7abd0cfe367de4666d6edbb8525bffe5222f0702c3096dec0884ce572f5a15c423fdf44d01dd99c61d
+ </inline>
+ <curve>secg/secp521r1</curve>
+ <onekey>wycheproof/cve_2017_10176/secp521r1/1s</onekey>
+ <otherkey>wycheproof/cve_2017_10176/secp521r1/1w</otherkey>
+ </result>
+ <result>
+ <id>cve_2017_8932/secp256r1/1test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x4d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3</inline>
+ <curve>secg/secp256r1</curve>
+ <onekey>wycheproof/cve_2017_8932/secp256r1/1s</onekey>
+ <otherkey>wycheproof/cve_2017_8932/secp256r1/1w</otherkey>
+ </result>
+ <result>
+ <id>cve_2017_8932/secp256r1/2test</id>
+ <ka>DH_PLAIN</ka>
+ <inline>0x831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f17991</inline>
+ <curve>secg/secp256r1</curve>
+ <onekey>wycheproof/cve_2017_8932/secp256r1/2s</onekey>
+ <otherkey>wycheproof/cve_2017_8932/secp256r1/2w</otherkey>
+ </result>
+</results> \ No newline at end of file
diff --git a/src/cz/crcs/ectester/reader/CardMngr.java b/src/cz/crcs/ectester/reader/CardMngr.java
index 1e42c52..921a9c8 100644
--- a/src/cz/crcs/ectester/reader/CardMngr.java
+++ b/src/cz/crcs/ectester/reader/CardMngr.java
@@ -1,9 +1,9 @@
package cz.crcs.ectester.reader;
-import com.licel.jcardsim.io.CAD;
import com.licel.jcardsim.io.JavaxSmartCardInterface;
import cz.crcs.ectester.common.util.ByteUtil;
import javacard.framework.AID;
+import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javax.smartcardio.*;
@@ -19,7 +19,6 @@ public class CardMngr {
private Card card = null;
// Simulator related attributes
- private CAD cad = null;
private JavaxSmartCardInterface simulator = null;
private boolean simulate = false;
@@ -351,13 +350,11 @@ public class CardMngr {
return sendAPDU(commandAPDU);
}
- public boolean prepareLocalSimulatorApplet(byte[] appletAIDArray, byte[] installData, Class appletClass) {
- System.setProperty("com.licel.jcardsim.terminal.type", "2");
- cad = new CAD(System.getProperties());
- simulator = (JavaxSmartCardInterface) cad.getCardInterface();
+ public boolean prepareLocalSimulatorApplet(byte[] appletAIDArray, byte[] installData, Class<? extends Applet> appletClass) {
+ simulator = new JavaxSmartCardInterface();
AID appletAID = new AID(appletAIDArray, (short) 0, (byte) appletAIDArray.length);
- AID appletAIDRes = simulator.installApplet(appletAID, appletClass, installData, (short) 0, (byte) installData.length);
+ simulator.installApplet(appletAID, appletClass, installData, (short) 0, (byte) installData.length);
return simulator.selectApplet(appletAID);
}
diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java
index 5e3a3fe..4a7d779 100644
--- a/src/cz/crcs/ectester/reader/ECTesterReader.java
+++ b/src/cz/crcs/ectester/reader/ECTesterReader.java
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2016-2017 Petr Svenda <petr@svenda.com>
+ * ECTester, tool for testing Elliptic curve cryptography implementations.
+ * Copyright (c) 2016-2018 Petr Svenda <petr@svenda.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,18 +25,17 @@ package cz.crcs.ectester.reader;
import cz.crcs.ectester.applet.ECTesterApplet;
import cz.crcs.ectester.applet.EC_Consts;
import cz.crcs.ectester.common.cli.CLITools;
+import cz.crcs.ectester.common.cli.Colors;
import cz.crcs.ectester.common.ec.EC_Params;
import cz.crcs.ectester.common.output.OutputLogger;
import cz.crcs.ectester.common.output.TestWriter;
-import cz.crcs.ectester.common.test.TestException;
import cz.crcs.ectester.common.util.ByteUtil;
import cz.crcs.ectester.common.util.CardUtil;
+import cz.crcs.ectester.common.util.FileUtil;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.reader.command.Command;
+import cz.crcs.ectester.reader.output.FileTestWriter;
import cz.crcs.ectester.reader.output.ResponseWriter;
-import cz.crcs.ectester.reader.output.TextTestWriter;
-import cz.crcs.ectester.reader.output.XMLTestWriter;
-import cz.crcs.ectester.reader.output.YAMLTestWriter;
import cz.crcs.ectester.reader.response.Response;
import cz.crcs.ectester.reader.test.*;
import javacard.security.KeyPair;
@@ -44,21 +44,24 @@ import org.apache.commons.cli.*;
import javax.smartcardio.CardException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
+import java.net.URL;
+import java.net.URLClassLoader;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
+import java.util.jar.Manifest;
-import static cz.crcs.ectester.applet.ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH;
-import static cz.crcs.ectester.applet.ECTesterApplet.Signature_ALG_ECDSA_SHA;
+import static cz.crcs.ectester.applet.EC_Consts.KeyAgreement_ALG_EC_SVDP_DH;
+import static cz.crcs.ectester.applet.EC_Consts.Signature_ALG_ECDSA_SHA;
/**
* Reader part of ECTester, a tool for testing Elliptic curve support on javacards.
*
* @author Petr Svenda petr@svenda.com
* @author Jan Jancar johny@neuromancer.sk
- * @version v0.1.0
+ * @version v0.2.0
*/
public class ECTesterReader {
private CardMngr cardManager;
@@ -67,21 +70,40 @@ public class ECTesterReader {
private Config cfg;
private Options opts = new Options();
- private static final String VERSION = "v0.1.0";
- private static final String DESCRIPTION = "ECTesterReader " + VERSION + ", a javacard Elliptic Curve Cryptography support tester/utility.";
- private static final String LICENSE = "MIT Licensed\nCopyright (c) 2016-2017 Petr Svenda <petr@svenda.com>";
- private static final String CLI_HEADER = "\n" + DESCRIPTION + "\n\n";
- private static final String CLI_FOOTER = "\n" + LICENSE;
+ public static final String VERSION = "v0.2.0";
+ public static String GIT_COMMIT = "";
+ private static String DESCRIPTION;
+ private static String LICENSE = "MIT Licensed\nCopyright (c) 2016-2018 Petr Svenda <petr@svenda.com>";
+ private static String CLI_HEADER;
+ private static String CLI_FOOTER = "\n" + LICENSE;
private static final byte[] SELECT_ECTESTERAPPLET = {(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x0a,
(byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x30, (byte) 0x31};
private static final byte[] AID = {(byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x30, (byte) 0x31};
private static final byte[] INSTALL_DATA = new byte[10];
+ static {
+ URLClassLoader cl = (URLClassLoader) ECTesterReader.class.getClassLoader();
+ try {
+ URL url = cl.findResource("META-INF/MANIFEST.MF");
+ 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.";
+ CLI_HEADER = "\n" + DESCRIPTION + "\n\n";
+ ;
+ }
+
private void run(String[] args) {
try {
CommandLine cli = parseArgs(args);
+ cfg = new Config();
+ boolean optsOk = cfg.readOptions(cli);
+
//if help, print and quit
if (cli.hasOption("help")) {
CLITools.help("ECTesterReader.jar", CLI_HEADER, opts, CLI_FOOTER, true);
@@ -90,10 +112,9 @@ public class ECTesterReader {
CLITools.version(DESCRIPTION, LICENSE);
return;
}
- cfg = new Config();
- //if not, read other options first, into attributes, then do action
- if (!cfg.readOptions(cli)) {
+ //if opts failed, quit
+ if (!optsOk) {
return;
}
@@ -103,18 +124,23 @@ public class ECTesterReader {
return;
}
+ if (cli.hasOption("list-suites")) {
+ listSuites();
+ return;
+ }
+
//init CardManager
cardManager = new CardMngr(cfg.verbose, cfg.simulate);
//connect or simulate connection
if (cfg.simulate) {
if (!cardManager.prepareLocalSimulatorApplet(AID, INSTALL_DATA, ECTesterApplet.class)) {
- System.err.println("Failed to establish a simulator.");
+ System.err.println(Colors.error("Failed to establish a simulator."));
System.exit(1);
}
} else {
if (!cardManager.connectToCardSelect()) {
- System.err.println("Failed to connect to card.");
+ System.err.println(Colors.error("Failed to connect to card."));
System.exit(1);
}
cardManager.send(SELECT_ECTESTERAPPLET);
@@ -143,7 +169,7 @@ public class ECTesterReader {
logger.close();
} catch (MissingOptionException moex) {
- System.err.println("Missing required options, one of:");
+ System.err.println(Colors.error("Missing required options, one of:"));
for (Object opt : moex.getMissingOptions().toArray()) {
if (opt instanceof OptionGroup) {
for (Option o : ((OptionGroup) opt).getOptions()) {
@@ -171,14 +197,14 @@ public class ECTesterReader {
}
}
} catch (MissingArgumentException maex) {
- System.err.println("Option, " + maex.getOption().getOpt() + " requires an argument: " + maex.getOption().getArgName());
+ System.err.println(Colors.error("Option, " + maex.getOption().getOpt() + " requires an argument: " + maex.getOption().getArgName()));
} catch (NumberFormatException nfex) {
- System.err.println("Not a number. " + nfex.getMessage());
+ System.err.println(Colors.error("Not a number. " + nfex.getMessage()));
} catch (FileNotFoundException fnfe) {
- System.err.println("File " + fnfe.getMessage() + " not found.");
+ System.err.println(Colors.error("File " + fnfe.getMessage() + " not found."));
} catch (ParseException | IOException ex) {
- System.err.println(ex.getMessage());
- } catch (CardException | TestException ex) {
+ System.err.println(Colors.error(ex.getMessage()));
+ } catch (CardException ex) {
if (logger != null)
logger.println(ex.getMessage());
ex.printStackTrace();
@@ -236,10 +262,12 @@ public class ECTesterReader {
* -l / --log [log_file]
*
* -f / --fresh
+ * --cleanup
* -s / --simulate
* -y / --yes
* -ka/ --ka-type <type>
* -sig/--sig-type <type>
+ * -C / --color
*/
OptionGroup actions = new OptionGroup();
actions.setRequired(true);
@@ -247,10 +275,11 @@ public class ECTesterReader {
actions.addOption(Option.builder("h").longOpt("help").desc("Print help.").build());
actions.addOption(Option.builder("ln").longOpt("list-named").desc("Print the list of supported named curves and keys.").hasArg().argName("what").optionalArg(true).build());
actions.addOption(Option.builder("e").longOpt("export").desc("Export the defaut curve parameters of the card(if any).").build());
- actions.addOption(Option.builder("g").longOpt("generate").desc("Generate [amount] of EC keys.").hasArg().argName("amount").optionalArg(true).build());
- actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. [test_suite]:\n- default:\n- invalid:\n- twist:\n- wrong:\n- composite:\n- test-vectors:").hasArg().argName("test_suite").optionalArg(true).build());
+ actions.addOption(Option.builder("g").longOpt("generate").desc("Generate <amount> of EC keys.").hasArg().argName("amount").optionalArg(true).build());
+ actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. Optionally specify a test number to run only a part of a test suite. <test_suite>:\n- default:\n- compression:\n- invalid:\n- twist:\n- degenerate:\n- cofactor:\n- wrong:\n- composite:\n- test-vectors:\n- edge-cases:\n- miscellaneous:").hasArg().argName("test_suite[:from[:to]]").optionalArg(true).build());
actions.addOption(Option.builder("dh").longOpt("ecdh").desc("Do EC KeyAgreement (ECDH...), [count] times.").hasArg().argName("count").optionalArg(true).build());
actions.addOption(Option.builder("dsa").longOpt("ecdsa").desc("Sign data with ECDSA, [count] times.").hasArg().argName("count").optionalArg(true).build());
+ actions.addOption(Option.builder("ls").longOpt("list-suites").desc("List supported test suites.").build());
opts.addOptionGroup(actions);
@@ -284,22 +313,45 @@ public class ECTesterReader {
opts.addOptionGroup(key);
opts.addOption(Option.builder("i").longOpt("input").desc("Input from file <input_file>, for ECDSA signing.").hasArg().argName("input_file").build());
- opts.addOption(Option.builder("o").longOpt("output").desc("Output into file <output_file>.").hasArg().argName("output_file").build());
+ opts.addOption(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").build());
opts.addOption(Option.builder("l").longOpt("log").desc("Log output into file [log_file].").hasArg().argName("log_file").optionalArg(true).build());
opts.addOption(Option.builder("v").longOpt("verbose").desc("Turn on verbose logging.").build());
opts.addOption(Option.builder().longOpt("format").desc("Output format to use. One of: text,yml,xml.").hasArg().argName("format").build());
opts.addOption(Option.builder("f").longOpt("fresh").desc("Generate fresh keys (set domain parameters before every generation).").build());
+ opts.addOption(Option.builder().longOpt("cleanup").desc("Send the cleanup command trigerring 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("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());
+ opts.addOption(Option.builder("C").longOpt("color").desc("Print stuff with color, requires ANSI terminal.").build());
CommandLineParser parser = new DefaultParser();
return parser.parse(opts, args);
}
+ private void listSuites() {
+ CardTestSuite[] suites = new CardTestSuite[]{
+ new CardDefaultSuite(null, null, null),
+ new CardTestVectorSuite(null, null, null),
+ new CardCompressionSuite(null, null, null),
+ new CardWrongSuite(null, null, null),
+ new CardDegenerateSuite(null, null, null),
+ new CardCofactorSuite(null, null, null),
+ new CardCompositeSuite(null, null, null),
+ new CardInvalidSuite(null, null, null),
+ new CardEdgeCasesSuite(null, null, null),
+ new CardTwistSuite(null, null, null),
+ new CardMiscSuite(null, null, null)};
+ for (CardTestSuite suite : suites) {
+ System.out.println(" - " + Colors.bold(suite.getName()));
+ for (String line : suite.getDescription()) {
+ System.out.println("\t" + line);
+ }
+ }
+ }
+
/**
* Exports default card/simulation EC domain parameters to output file.
*
@@ -310,17 +362,17 @@ public class ECTesterReader {
byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
List<Response> sent = new LinkedList<>();
- sent.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass).send());
+ sent.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.bits, keyClass).send());
sent.add(new Command.Clear(cardManager, ECTesterApplet.KEYPAIR_LOCAL).send());
sent.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL).send());
// Cofactor generally isn't set on the default curve parameters on cards,
// since its not necessary for ECDH, only ECDHC which not many cards implement
// TODO: check if its assumend to be == 1?
- short domainAll = cfg.primeField ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M;
- short domain = (short) (domainAll ^ EC_Consts.PARAMETER_K);
- Response.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, domainAll).send();
+ short domain = cfg.primeField ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M;
+ Response.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, domain).send();
if (!export.successful()) {
+ domain = (short) (domain ^ EC_Consts.PARAMETER_K);
export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, domain).send();
}
sent.add(export);
@@ -328,11 +380,19 @@ public class ECTesterReader {
for (Response r : sent) {
respWriter.outputResponse(r);
}
+ if (cfg.cleanup) {
+ Response cleanup = new Command.Cleanup(cardManager).send();
+ respWriter.outputResponse(cleanup);
+ }
- EC_Params exported = new EC_Params(domain, export.getParams());
-
- FileOutputStream out = new FileOutputStream(cfg.output);
- exported.writeCSV(out);
+ PrintStream out = new PrintStream(FileUtil.openStream(cfg.outputs));
+ byte[][] params = export.getParams();
+ for (int i = 0; i < params.length; ++i) {
+ out.print(ByteUtil.bytesToHex(params[i], false));
+ if (i != params.length - 1) {
+ out.print(",");
+ }
+ }
out.close();
}
@@ -345,11 +405,11 @@ public class ECTesterReader {
private void generate() throws CardException, IOException {
byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
- Response allocate = new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass).send();
+ Response allocate = new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.bits, keyClass).send();
respWriter.outputResponse(allocate);
- Command curve = Command.prepareCurve(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass);
+ Command curve = Command.prepareCurve(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_LOCAL, cfg.bits, keyClass);
- FileWriter keysFile = new FileWriter(cfg.output);
+ OutputStreamWriter keysFile = FileUtil.openFiles(cfg.outputs);
keysFile.write("index;time;pubW;privS\n");
int generated = 0;
@@ -363,6 +423,7 @@ public class ECTesterReader {
Command.Generate generate = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL);
Response.Generate response = generate.send();
long elapsed = response.getDuration();
+ respWriter.outputResponse(response);
Response.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_BOTH, EC_Consts.PARAMETERS_KEYPAIR).send();
@@ -371,11 +432,10 @@ public class ECTesterReader {
retry++;
continue;
} else {
- System.err.println("Keys could not be generated.");
+ System.err.println(Colors.error("Keys could not be generated/exported."));
break;
}
}
- respWriter.outputResponse(response);
String pub = ByteUtil.bytesToHex(export.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W), false);
String priv = ByteUtil.bytesToHex(export.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S), false);
@@ -384,8 +444,10 @@ public class ECTesterReader {
keysFile.flush();
generated++;
}
- Response cleanup = new Command.Cleanup(cardManager).send();
- respWriter.outputResponse(cleanup);
+ if (cfg.cleanup) {
+ Response cleanup = new Command.Cleanup(cardManager).send();
+ respWriter.outputResponse(cleanup);
+ }
keysFile.close();
}
@@ -393,27 +455,10 @@ public class ECTesterReader {
/**
* Tests Elliptic curve support for a given curve/curves.
*
- * @throws CardException if APDU transmission fails
- * @throws IOException if an IO error occurs when writing to key file.
+ * @throws IOException if an IO error occurs
*/
- private void test() throws IOException, TestException, ParserConfigurationException {
- TestWriter writer = null;
- if (cfg.format == null) {
- writer = new TextTestWriter(logger.getPrintStream());
- } else {
- switch (cfg.format) {
- case "text":
- writer = new TextTestWriter(logger.getPrintStream());
- break;
- case "xml":
- writer = new XMLTestWriter(logger.getOutputStream());
- break;
- case "yaml":
- case "yml":
- writer = new YAMLTestWriter(logger.getPrintStream());
- break;
- }
- }
+ private void test() throws ParserConfigurationException, IOException {
+ TestWriter writer = new FileTestWriter(cfg.format, true, cfg.outputs);
CardTestSuite suite;
@@ -424,10 +469,17 @@ public class ECTesterReader {
case "test-vectors":
suite = new CardTestVectorSuite(writer, cfg, cardManager);
break;
+ case "compression":
+ suite = new CardCompressionSuite(writer, cfg, cardManager);
+ break;
+ case "misc":
+ case "miscellaneous":
+ suite = new CardMiscSuite(writer, cfg, cardManager);
+ break;
default:
// These run are dangerous, prompt before them.
System.out.println("The test you selected (" + cfg.testSuite + ") is potentially dangerous.");
- System.out.println("Some of these run have caused temporary DoS of some cards.");
+ System.out.println("Some of these run have caused temporary(or even permanent) DoS of some cards.");
if (!cfg.yes) {
System.out.print("Do you want to proceed? (y/n): ");
Scanner in = new Scanner(System.in);
@@ -439,25 +491,34 @@ public class ECTesterReader {
}
switch (cfg.testSuite) {
case "wrong":
- suite = new CardWrongCurvesSuite(writer, cfg, cardManager);
+ suite = new CardWrongSuite(writer, cfg, cardManager);
break;
case "composite":
- suite = new CardCompositeCurvesSuite(writer, cfg, cardManager);
+ suite = new CardCompositeSuite(writer, cfg, cardManager);
break;
case "invalid":
- suite = new CardInvalidCurvesSuite(writer, cfg, cardManager);
+ suite = new CardInvalidSuite(writer, cfg, cardManager);
+ break;
+ case "degenerate":
+ suite = new CardDegenerateSuite(writer, cfg, cardManager);
break;
case "twist":
- suite = new CardTwistTestSuite(writer, cfg, cardManager);
+ suite = new CardTwistSuite(writer, cfg, cardManager);
+ break;
+ case "cofactor":
+ suite = new CardCofactorSuite(writer, cfg, cardManager);
+ break;
+ case "edge-cases":
+ suite = new CardEdgeCasesSuite(writer, cfg, cardManager);
break;
default:
- System.err.println("Unknown test suite.");
+ System.err.println(Colors.error("Unknown test suite."));
return;
}
break;
}
- suite.run();
+ suite.run(cfg.testFrom, cfg.testTo);
}
/**
@@ -470,8 +531,8 @@ public class ECTesterReader {
byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
List<Response> prepare = new LinkedList<>();
prepare.add(new Command.AllocateKeyAgreement(cardManager, cfg.ECKAType).send()); // Prepare KeyAgreement or required type
- prepare.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, keyClass).send());
- Command curve = Command.prepareCurve(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, keyClass);
+ prepare.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, cfg.bits, keyClass).send());
+ Command curve = Command.prepareCurve(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_BOTH, cfg.bits, keyClass);
if (curve != null)
prepare.add(curve.send());
@@ -488,9 +549,9 @@ public class ECTesterReader {
generate.add(Command.prepareKey(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_REMOTE));
}
- FileWriter out = null;
- if (cfg.output != null) {
- out = new FileWriter(cfg.output);
+ OutputStreamWriter out = null;
+ if (cfg.outputs != null) {
+ out = FileUtil.openFiles(cfg.outputs);
out.write("index;time;pubW;privS;secret\n");
}
@@ -498,24 +559,24 @@ public class ECTesterReader {
int done = 0;
while (done < cfg.ECKACount) {
List<Response> ecdh = Command.sendAll(generate);
+ for (Response r : ecdh) {
+ respWriter.outputResponse(r);
+ }
Response.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETERS_KEYPAIR).send();
- ecdh.add(export);
+ respWriter.outputResponse(export);
byte pubkey_bytes[] = export.getParameter(pubkey, EC_Consts.PARAMETER_W);
byte privkey_bytes[] = export.getParameter(privkey, EC_Consts.PARAMETER_S);
- Response.ECDH perform = new Command.ECDH(cardManager, pubkey, privkey, ECTesterApplet.EXPORT_TRUE, EC_Consts.CORRUPTION_NONE, cfg.ECKAType).send();
- ecdh.add(perform);
- for (Response r : ecdh) {
- respWriter.outputResponse(r);
- }
+ Response.ECDH perform = new Command.ECDH(cardManager, pubkey, privkey, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, cfg.ECKAType).send();
+ respWriter.outputResponse(perform);
if (!perform.successful() || !perform.hasSecret()) {
if (retry < 10) {
++retry;
continue;
} else {
- System.err.println("Couldn't obtain ECDH secret from card response.");
+ System.err.println(Colors.error("Couldn't obtain ECDH secret from card response."));
break;
}
}
@@ -526,8 +587,10 @@ public class ECTesterReader {
++done;
}
- Response cleanup = new Command.Cleanup(cardManager).send();
- respWriter.outputResponse(cleanup);
+ if (cfg.cleanup) {
+ Response cleanup = new Command.Cleanup(cardManager).send();
+ respWriter.outputResponse(cleanup);
+ }
if (out != null)
out.close();
@@ -561,8 +624,8 @@ public class ECTesterReader {
byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
List<Response> prepare = new LinkedList<>();
prepare.add(new Command.AllocateSignature(cardManager, cfg.ECDSAType).send());
- prepare.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass).send());
- Command curve = Command.prepareCurve(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass);
+ prepare.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.bits, keyClass).send());
+ Command curve = Command.prepareCurve(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_LOCAL, cfg.bits, keyClass);
if (curve != null)
prepare.add(curve.send());
@@ -570,30 +633,25 @@ public class ECTesterReader {
respWriter.outputResponse(r);
}
- FileWriter out = null;
- if (cfg.output != null) {
- out = new FileWriter(cfg.output);
+ OutputStreamWriter out = FileUtil.openFiles(cfg.outputs);
+ if (out != null) {
out.write("index;time;signature\n");
}
int retry = 0;
int done = 0;
while (done < cfg.ECDSACount) {
- List<Response> ecdsa = new LinkedList<>();
- ecdsa.add(generate.send());
+ respWriter.outputResponse(generate.send());
Response.ECDSA perform = new Command.ECDSA(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.ECDSAType, ECTesterApplet.EXPORT_TRUE, data).send();
- ecdsa.add(perform);
- for (Response r : ecdsa) {
- respWriter.outputResponse(r);
- }
+ respWriter.outputResponse(perform);
if (!perform.successful() || !perform.hasSignature()) {
if (retry < 10) {
++retry;
continue;
} else {
- System.err.println("Couldn't obtain ECDSA signature from card response.");
+ System.err.println(Colors.error("Couldn't obtain ECDSA signature from card response."));
break;
}
}
@@ -604,9 +662,10 @@ public class ECTesterReader {
++done;
}
- Response cleanup = new Command.Cleanup(cardManager).send();
- respWriter.outputResponse(cleanup);
-
+ if (cfg.cleanup) {
+ Response cleanup = new Command.Cleanup(cardManager).send();
+ respWriter.outputResponse(cleanup);
+ }
if (out != null)
out.close();
}
@@ -647,15 +706,19 @@ public class ECTesterReader {
public boolean verbose = false;
public String input;
- public String output;
+ public String[] outputs;
public boolean fresh = false;
+ public boolean cleanup = false;
public boolean simulate = false;
public boolean yes = false;
public String format;
+ public boolean color;
//Action-related options
public String listNamed;
public String testSuite;
+ public int testFrom;
+ public int testTo;
public int generateAmount;
public int ECKACount;
public byte ECKAType = KeyAgreement_ALG_EC_SVDP_DH;
@@ -698,83 +761,82 @@ public class ECTesterReader {
verbose = cli.hasOption("verbose");
input = cli.getOptionValue("input");
- output = cli.getOptionValue("output");
+ outputs = cli.getOptionValues("output");
fresh = cli.hasOption("fresh");
+ cleanup = cli.hasOption("cleanup");
simulate = cli.hasOption("simulate");
yes = cli.hasOption("yes");
+ color = cli.hasOption("color");
+ Colors.enabled = color;
if (cli.hasOption("list-named")) {
listNamed = cli.getOptionValue("list-named");
return true;
}
- format = cli.getOptionValue("format", "text");
+ format = cli.getOptionValue("format");
String formats[] = new String[]{"text", "xml", "yaml", "yml"};
- if (!Arrays.asList(formats).contains(format)) {
- System.err.println("Wrong output format " + format + ". Should be one of " + Arrays.toString(formats));
+ if (format != null && !Arrays.asList(formats).contains(format)) {
+ System.err.println(Colors.error("Wrong output format " + format + ". Should be one of " + Arrays.toString(formats)));
return false;
}
if ((key != null || namedKey != null) && (anyPublicKey || anyPrivateKey)) {
- System.err.print("Can only specify the whole key with --key/--named-key or pubkey and privkey with --public/--named-public and --private/--named-private.");
+ System.err.print(Colors.error("Can only specify the whole key with --key/--named-key or pubkey and privkey with --public/--named-public and --private/--named-private."));
return false;
}
if (bits < 0) {
- System.err.println("Bit-size must not be negative.");
- return false;
- }
- if (bits == 0 && !all) {
- System.err.println("You must specify either bit-size with -b or all bit-sizes with -a.");
+ System.err.println(Colors.error("Bit-size must not be negative."));
return false;
}
if (key != null && namedKey != null || publicKey != null && namedPublicKey != null || privateKey != null && namedPrivateKey != null) {
- System.err.println("You cannot specify both a named key and a key file.");
+ System.err.println(Colors.error("You cannot specify both a named key and a key file."));
return false;
}
if (cli.hasOption("export")) {
if (primeField == binaryField) {
- System.err.print("Need to specify field with -fp or -f2m. (not both)");
+ System.err.print(Colors.error("Need to specify field with -fp or -f2m. (not both)"));
return false;
}
if (anyKeypart) {
- System.err.println("Keys should not be specified when exporting curve params.");
+ System.err.println(Colors.error("Keys should not be specified when exporting curve params."));
return false;
}
if (namedCurve != null || customCurve || curveFile != null) {
- System.err.println("Specifying a curve for curve export makes no sense.");
+ System.err.println(Colors.error("Specifying a curve for curve export makes no sense."));
return false;
}
- if (output == null) {
- System.err.println("You have to specify an output file for curve parameter export.");
+ if (outputs == null) {
+ System.err.println(Colors.error("You have to specify an output file for curve parameter export."));
return false;
}
- if (all) {
- System.err.println("You have to specify curve bit-size with -b");
+ if (all || bits == 0) {
+ System.err.println(Colors.error("You have to specify curve bit-size with -b"));
return false;
}
} else if (cli.hasOption("generate")) {
if (primeField == binaryField) {
- System.err.print("Need to specify field with -fp or -f2m. (not both)");
+ System.err.print(Colors.error("Need to specify field with -fp or -f2m. (not both)"));
return false;
}
if (anyKeypart) {
- System.err.println("Keys should not be specified when generating keys.");
+ System.err.println(Colors.error("Keys should not be specified when generating keys."));
return false;
}
- if (output == null) {
- System.err.println("You have to specify an output file for the key generation process.");
+ if (outputs == null) {
+ System.err.println(Colors.error("You have to specify an output file for the key generation process."));
return false;
}
- if (all) {
- System.err.println("You have to specify curve bit-size with -b");
+ if (all || bits == 0) {
+ System.err.println(Colors.error("You have to specify curve bit-size with -b"));
return false;
}
generateAmount = Integer.parseInt(cli.getOptionValue("generate", "0"));
if (generateAmount < 0) {
- System.err.println("Amount of keys generated cant be negative.");
+ System.err.println(Colors.error("Amount of keys generated cant be negative."));
return false;
}
} else if (cli.hasOption("test")) {
@@ -783,47 +845,74 @@ public class ECTesterReader {
primeField = true;
}
- testSuite = cli.getOptionValue("test", "default").toLowerCase();
- String[] tests = new String[]{"default", "composite", "invalid", "test-vectors", "wrong", "twist"};
+ String suiteOpt = cli.getOptionValue("test", "default").toLowerCase();
+ if (suiteOpt.contains(":")) {
+ String[] parts = suiteOpt.split(":");
+ testSuite = parts[0];
+ try {
+ testFrom = Integer.parseInt(parts[1]);
+ } catch (NumberFormatException nfe) {
+ System.err.println("Invalid test from number: " + parts[1] + ".");
+ return false;
+ }
+ if (parts.length == 3) {
+ try {
+ testTo = Integer.parseInt(parts[2]);
+ } catch (NumberFormatException nfe) {
+ System.err.println("Invalid test to number: " + parts[2] + ".");
+ return false;
+ }
+ } else if (parts.length != 2) {
+ System.err.println("Invalid test suite selection.");
+ return false;
+ } else {
+ testTo = -1;
+ }
+ } else {
+ testSuite = suiteOpt;
+ testFrom = 0;
+ testTo = -1;
+ }
+ String[] tests = new String[]{"default", "composite", "compression", "invalid", "degenerate", "test-vectors", "wrong", "twist", "cofactor", "edge-cases", "miscellaneous"};
if (!Arrays.asList(tests).contains(testSuite)) {
- System.err.println("Unknown test suite " + testSuite + ". Should be one of: " + Arrays.toString(tests));
+ System.err.println(Colors.error("Unknown test suite " + testSuite + ". Should be one of: " + Arrays.toString(tests)));
return false;
}
} else if (cli.hasOption("ecdh")) {
if (primeField == binaryField) {
- System.err.print("Need to specify field with -fp or -f2m. (not both)");
+ System.err.print(Colors.error("Need to specify field with -fp or -f2m. (not both)"));
return false;
}
- if (all) {
- System.err.println("You have to specify curve bit-size with -b");
+ if (all || bits == 0) {
+ System.err.println(Colors.error("You have to specify curve bit-size with -b"));
return false;
}
ECKACount = Integer.parseInt(cli.getOptionValue("ecdh", "1"));
if (ECKACount <= 0) {
- System.err.println("ECDH count cannot be <= 0.");
+ System.err.println(Colors.error("ECDH count cannot be <= 0."));
return false;
}
ECKAType = CardUtil.parseKAType(cli.getOptionValue("ka-type", "1"));
} else if (cli.hasOption("ecdsa")) {
if (primeField == binaryField) {
- System.err.print("Need to specify field with -fp or -f2m. (but not both)");
+ System.err.print(Colors.error("Need to specify field with -fp or -f2m. (but not both)"));
return false;
}
- if (all) {
- System.err.println("You have to specify curve bit-size with -b");
+ if (all || bits == 0) {
+ System.err.println(Colors.error("You have to specify curve bit-size with -b"));
return false;
}
if ((anyPublicKey) != (anyPrivateKey) && !anyKey) {
- System.err.println("You cannot only specify a part of a keypair.");
+ System.err.println(Colors.error("You cannot only specify a part of a keypair."));
return false;
}
ECDSACount = Integer.parseInt(cli.getOptionValue("ecdsa", "1"));
if (ECDSACount <= 0) {
- System.err.println("ECDSA count cannot be <= 0.");
+ System.err.println(Colors.error("ECDSA count cannot be <= 0."));
return false;
}
diff --git a/src/cz/crcs/ectester/reader/command/Command.java b/src/cz/crcs/ectester/reader/command/Command.java
index 5a6906c..858b05f 100644
--- a/src/cz/crcs/ectester/reader/command/Command.java
+++ b/src/cz/crcs/ectester/reader/command/Command.java
@@ -2,15 +2,16 @@ package cz.crcs.ectester.reader.command;
import cz.crcs.ectester.applet.ECTesterApplet;
import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+import cz.crcs.ectester.common.ec.EC_Key;
+import cz.crcs.ectester.common.ec.EC_Keypair;
+import cz.crcs.ectester.common.ec.EC_Params;
import cz.crcs.ectester.common.util.ByteUtil;
+import cz.crcs.ectester.common.util.CardUtil;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.reader.CardMngr;
import cz.crcs.ectester.reader.ECTesterReader;
import cz.crcs.ectester.reader.response.Response;
-import cz.crcs.ectester.common.ec.EC_Curve;
-import cz.crcs.ectester.common.ec.EC_Key;
-import cz.crcs.ectester.common.ec.EC_Keypair;
-import cz.crcs.ectester.common.ec.EC_Params;
import javacard.security.KeyPair;
import javax.smartcardio.CardException;
@@ -24,7 +25,7 @@ import java.util.List;
/**
* @author Jan Jancar johny@neuromancer.sk
*/
-public abstract class Command {
+public abstract class Command implements Cloneable {
CommandAPDU cmd;
CardMngr cardManager;
@@ -46,6 +47,13 @@ public abstract class Command {
return result;
}
+ public abstract String getDescription();
+
+ @Override
+ protected Command clone() throws CloneNotSupportedException {
+ return (Command) super.clone();
+ }
+
/**
* @param keyPair which keyPair/s (local/remote) to set curve domain parameters on
@@ -179,111 +187,117 @@ public abstract class Command {
return new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, params, data);
}
-
/**
*
*/
- public static class Allocate extends Command {
- private byte keyPair;
- private short keyLength;
- private byte keyClass;
+ public static class AllocateKeyAgreement extends Command {
+ private byte kaType;
/**
- * Creates the INS_ALLOCATE instruction.
+ * Creates the INS_ALLOCATE_KA instruction.
*
* @param cardManager cardManager to send APDU through
- * @param keyPair which keyPair to use, local/remote (KEYPAIR_* | ...)
- * @param keyLength key length to set
- * @param keyClass key class to allocate
+ * @param kaType which type of KeyAgreement to use
*/
- public Allocate(CardMngr cardManager, byte keyPair, short keyLength, byte keyClass) {
+ public AllocateKeyAgreement(CardMngr cardManager, byte kaType) {
super(cardManager);
- this.keyPair = keyPair;
- this.keyLength = keyLength;
- this.keyClass = keyClass;
-
- byte[] data = new byte[]{0, 0, keyClass};
- ByteUtil.setShort(data, 0, keyLength);
- this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE, keyPair, 0x00, data);
+ this.kaType = kaType;
+ byte[] data = new byte[]{kaType};
+ this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE_KA, 0x00, 0x00, data);
}
@Override
- public Response.Allocate send() throws CardException {
+ public Response.AllocateKeyAgreement send() throws CardException {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.Allocate(response, elapsed, keyPair, keyLength, keyClass);
+ return new Response.AllocateKeyAgreement(response, getDescription(), elapsed, kaType);
}
@Override
- public String toString() {
- return "Allocate";
+ public String getDescription() {
+ return String.format("Allocate KeyAgreement(%s) object", CardUtil.getKATypeString(kaType));
}
}
/**
*
*/
- public static class AllocateKeyAgreement extends Command {
- private byte kaType;
+ public static class AllocateSignature extends Command {
+ private byte sigType;
/**
- * Creates the INS_ALLOCATE_KA instruction.
+ * Creates the INS_ALLOCATE_SIG instruction.
*
* @param cardManager cardManager to send APDU through
- * @param kaType which type of KeyAgreement to use
+ * @param sigType which type of Signature to use
*/
- public AllocateKeyAgreement(CardMngr cardManager, byte kaType) {
+ public AllocateSignature(CardMngr cardManager, byte sigType) {
super(cardManager);
- this.kaType = kaType;
- byte[] data = new byte[]{kaType};
- this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE_KA, 0x00, 0x00, data);
+ this.sigType = sigType;
+ byte[] data = new byte[]{sigType};
+ this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE_SIG, 0x00, 0x00, data);
}
@Override
- public Response.AllocateKeyAgreement send() throws CardException {
+ public Response.AllocateSignature send() throws CardException {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.AllocateKeyAgreement(response, elapsed, kaType);
+ return new Response.AllocateSignature(response, getDescription(), elapsed, sigType);
}
@Override
- public String toString() {
- return "AllocateKeyAgreement";
+ public String getDescription() {
+ return String.format("Allocate Signature(%s) object", CardUtil.getSigTypeString(sigType));
}
}
/**
*
*/
- public static class AllocateSignature extends Command {
- private byte sigType;
+ public static class Allocate extends Command {
+ private byte keyPair;
+ private short keyLength;
+ private byte keyClass;
/**
- * Creates the INS_ALLOCATE_SIG instruction.
+ * Creates the INS_ALLOCATE instruction.
*
* @param cardManager cardManager to send APDU through
- * @param sigType which type of Signature to use
+ * @param keyPair which keyPair to use, local/remote (KEYPAIR_* | ...)
+ * @param keyLength key length to set
+ * @param keyClass key class to allocate
*/
- public AllocateSignature(CardMngr cardManager, byte sigType) {
+ public Allocate(CardMngr cardManager, byte keyPair, short keyLength, byte keyClass) {
super(cardManager);
- this.sigType = sigType;
- byte[] data = new byte[]{sigType};
- this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE_SIG, 0x00, 0x00, data);
+ this.keyPair = keyPair;
+ this.keyLength = keyLength;
+ this.keyClass = keyClass;
+
+ byte[] data = new byte[]{0, 0, keyClass};
+ ByteUtil.setShort(data, 0, keyLength);
+ this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE, keyPair, 0x00, data);
}
@Override
- public Response.AllocateSignature send() throws CardException {
+ public Response.Allocate send() throws CardException {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.AllocateSignature(response, elapsed, sigType);
+ return new Response.Allocate(response, getDescription(), elapsed, keyPair, keyLength, keyClass);
}
@Override
- public String toString() {
- return "AllocateSignature";
+ public String getDescription() {
+ String field = keyClass == KeyPair.ALG_EC_FP ? "ALG_EC_FP" : "ALG_EC_F2M";
+ String key;
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ key = "both keypairs";
+ } else {
+ key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
+ }
+ return String.format("Allocate %s %db %s", key, keyLength, field);
}
}
@@ -309,12 +323,18 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.Clear(response, elapsed, keyPair);
+ return new Response.Clear(response, getDescription(), elapsed, keyPair);
}
@Override
- public String toString() {
- return "Clear";
+ public String getDescription() {
+ String key;
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ key = "both keypairs";
+ } else {
+ key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
+ }
+ return String.format("Clear %s", key);
}
}
@@ -358,56 +378,85 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.Set(response, elapsed, keyPair, curve, params);
+ return new Response.Set(response, getDescription(), elapsed, keyPair, curve, params);
}
@Override
- public String toString() {
- return "Set";
+ public String getDescription() {
+ String name;
+ switch (curve) {
+ case EC_Consts.CURVE_default:
+ name = "default";
+ break;
+ case EC_Consts.CURVE_external:
+ name = "external";
+ break;
+ default:
+ name = "custom";
+ break;
+ }
+ String what = CardUtil.getParameterString(params);
+
+ String pair;
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ pair = "both keypairs";
+ } else {
+ pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
+ }
+ return String.format("Set %s %s parameters on %s", name, what, pair);
}
}
/**
*
*/
- public static class Corrupt extends Command {
+ public static class Transform extends Command {
private byte keyPair;
private byte key;
private short params;
- private byte corruption;
+ private short transformation;
/**
* @param cardManager cardManager to send APDU through
- * @param keyPair which keyPair to corrupt, local/remote (KEYPAIR_* || ...)
- * @param key key to corrupt (EC_Consts.KEY_* | ...)
- * @param params parameters to corrupt (EC_Consts.PARAMETER_* | ...)
- * @param corruption corruption type (EC_Consts.CORRUPTION_*)
+ * @param keyPair which keyPair to transform, local/remote (KEYPAIR_* || ...)
+ * @param key key to transform (EC_Consts.KEY_* | ...)
+ * @param params parameters to transform (EC_Consts.PARAMETER_* | ...)
+ * @param transformation transformation type (EC_Consts.TRANSFORMATION_*)
*/
- public Corrupt(CardMngr cardManager, byte keyPair, byte key, short params, byte corruption) {
+ public Transform(CardMngr cardManager, byte keyPair, byte key, short params, short transformation) {
super(cardManager);
this.keyPair = keyPair;
this.key = key;
this.params = params;
- this.corruption = corruption;
+ this.transformation = transformation;
- byte[] data = new byte[3];
+ byte[] data = new byte[4];
ByteUtil.setShort(data, 0, params);
- data[2] = corruption;
+ ByteUtil.setShort(data, 2, transformation);
- this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_CORRUPT, keyPair, key, data);
+ this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_TRANSFORM, keyPair, key, data);
}
@Override
- public Response.Corrupt send() throws CardException {
+ public Response.Transform send() throws CardException {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.Corrupt(response, elapsed, keyPair, key, params, corruption);
+ return new Response.Transform(response, getDescription(), elapsed, keyPair, key, params, transformation);
}
@Override
- public String toString() {
- return "Corrupt";
+ public String getDescription() {
+ String stringParams = CardUtil.getParams(params);
+ String transform = CardUtil.getTransformation(transformation);
+
+ String pair;
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ pair = "both keypairs";
+ } else {
+ pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
+ }
+ return String.format("Transform params %s of %s, %s", stringParams, pair, transform);
}
}
@@ -435,12 +484,18 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.Generate(response, elapsed, keyPair);
+ return new Response.Generate(response, getDescription(), elapsed, keyPair);
}
@Override
- public String toString() {
- return "Generate";
+ public String getDescription() {
+ String key;
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ key = "both keypairs";
+ } else {
+ key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
+ }
+ return String.format("Generate %s", key);
}
}
@@ -477,12 +532,26 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.Export(response, elapsed, keyPair, key, params);
+ return new Response.Export(response, getDescription(), elapsed, keyPair, key, params);
}
@Override
- public String toString() {
- return "Export";
+ public String getDescription() {
+ String what = CardUtil.getParameterString(params);
+
+ String source;
+ if (key == EC_Consts.KEY_BOTH) {
+ source = "both keys";
+ } else {
+ source = ((key == EC_Consts.KEY_PUBLIC) ? "public" : "private") + " key";
+ }
+ String pair;
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ pair = "both keypairs";
+ } else {
+ pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
+ }
+ return String.format("Export %s params from %s of %s", what, source, pair);
}
}
@@ -493,7 +562,7 @@ public abstract class Command {
private byte pubkey;
private byte privkey;
private byte export;
- private short corruption;
+ private short transformation;
private byte type;
/**
@@ -503,19 +572,19 @@ public abstract class Command {
* @param pubkey keyPair to use for public key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
* @param privkey keyPair to use for private key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
* @param export whether to export ECDH secret
- * @param corruption whether to invalidate the pubkey before ECDH (EC_Consts.CORRUPTION_* | ...)
+ * @param transformation whether to transform the pubkey before ECDH (EC_Consts.TRANSFORMATION_* | ...)
* @param type ECDH algorithm type (EC_Consts.KA_* | ...)
*/
- public ECDH(CardMngr cardManager, byte pubkey, byte privkey, byte export, short corruption, byte type) {
+ public ECDH(CardMngr cardManager, byte pubkey, byte privkey, byte export, short transformation, byte type) {
super(cardManager);
this.pubkey = pubkey;
this.privkey = privkey;
this.export = export;
- this.corruption = corruption;
+ this.transformation = transformation;
this.type = type;
- byte[] data = new byte[]{export, 0,0, type};
- ByteUtil.setShort(data, 1, corruption);
+ byte[] data = new byte[]{export, 0, 0, type};
+ ByteUtil.setShort(data, 1, transformation);
this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDH, pubkey, privkey, data);
}
@@ -525,12 +594,23 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.ECDH(response, elapsed, pubkey, privkey, export, corruption, type);
+ return new Response.ECDH(response, getDescription(), elapsed, pubkey, privkey, export, transformation, type);
}
@Override
- public String toString() {
- return "ECDH";
+ public String getDescription() {
+ String algo = CardUtil.getKATypeString(type);
+
+ String pub = pubkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
+ String priv = privkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
+
+ String validity;
+ if (transformation == EC_Consts.TRANSFORMATION_NONE) {
+ validity = "";
+ } else {
+ validity = String.format("(%s point)", CardUtil.getTransformation(transformation));
+ }
+ return String.format("%s of %s pubkey and %s privkey%s", algo, pub, priv, validity);
}
}
@@ -540,7 +620,7 @@ public abstract class Command {
public static class ECDH_direct extends Command {
private byte privkey;
private byte export;
- private short corruption;
+ private short transformation;
private byte type;
private byte[] pubkey;
@@ -550,20 +630,20 @@ public abstract class Command {
* @param cardManager cardManager to send APDU through
* @param privkey keyPair to use for private key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
* @param export whether to export ECDH secret
- * @param corruption whether to invalidate the pubkey before ECDH (EC_Consts.CORRUPTION_* | ...)
+ * @param transformation whether to transform the pubkey before ECDH (EC_Consts.TRANSFORMATION_* | ...)
* @param type EC KeyAgreement type
* @param pubkey pubkey data to do ECDH with.
*/
- public ECDH_direct(CardMngr cardManager, byte privkey, byte export, short corruption, byte type, byte[] pubkey) {
+ public ECDH_direct(CardMngr cardManager, byte privkey, byte export, short transformation, byte type, byte[] pubkey) {
super(cardManager);
this.privkey = privkey;
this.export = export;
- this.corruption = corruption;
+ this.transformation = transformation;
this.type = type;
this.pubkey = pubkey;
byte[] data = new byte[3 + pubkey.length];
- ByteUtil.setShort(data, 0, corruption);
+ ByteUtil.setShort(data, 0, transformation);
data[2] = type;
System.arraycopy(pubkey, 0, data, 3, pubkey.length);
@@ -575,12 +655,22 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.ECDH(response, elapsed, ECTesterApplet.KEYPAIR_REMOTE, privkey, export, corruption, type);
+ return new Response.ECDH(response, getDescription(), elapsed, ECTesterApplet.KEYPAIR_REMOTE, privkey, export, transformation, type);
}
@Override
- public String toString() {
- return "ECDH_direct";
+ public String getDescription() {
+ String algo = CardUtil.getKATypeString(type);
+
+ String priv = privkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
+
+ String validity;
+ if (transformation == EC_Consts.TRANSFORMATION_NONE) {
+ validity = "";
+ } else {
+ validity = String.format("(%s point)", CardUtil.getTransformation(transformation));
+ }
+ return String.format("%s of external pubkey and %s privkey%s", algo, priv, validity);
}
}
@@ -601,6 +691,10 @@ public abstract class Command {
*/
public ECDSA(CardMngr cardManager, byte keyPair, byte sigType, byte export, byte[] raw) {
super(cardManager);
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ throw new IllegalArgumentException();
+ }
+
this.keyPair = keyPair;
this.sigType = sigType;
this.export = export;
@@ -622,12 +716,124 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.ECDSA(response, elapsed, keyPair, sigType, export, raw);
+ return new Response.ECDSA(response, getDescription(), elapsed, keyPair, sigType, export, raw);
+ }
+
+ @Override
+ public String getDescription() {
+ String algo = CardUtil.getSigTypeString(sigType);
+ String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
+ String data = raw == null ? "random" : "provided";
+ return String.format("%s with %s keypair(%s data)", algo, key, data);
+ }
+ }
+
+ public static class ECDSA_sign extends Command {
+ private byte keyPair;
+ private byte sigType;
+ private byte export;
+ private byte[] raw;
+
+ /**
+ * Creates the INS_ECDSA_SIGN instruction.
+ *
+ * @param cardManager cardManager to send APDU through
+ * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
+ * @param sigType Signature type to use
+ * @param export whether to export ECDSA signature
+ * @param raw data to sign, can be null, in which case random data is signed.
+ */
+ public ECDSA_sign(CardMngr cardManager, byte keyPair, byte sigType, byte export, byte[] raw) {
+ super(cardManager);
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ throw new IllegalArgumentException();
+ }
+
+ this.keyPair = keyPair;
+ this.sigType = sigType;
+ this.export = export;
+ this.raw = raw;
+
+ int len = raw != null ? raw.length : 0;
+ byte[] data = new byte[3 + len];
+ data[0] = sigType;
+ ByteUtil.setShort(data, 1, (short) len);
+ if (raw != null) {
+ System.arraycopy(raw, 0, data, 3, len);
+ }
+
+ this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA_SIGN, keyPair, export, data);
+ }
+
+ @Override
+ public Response.ECDSA send() throws CardException {
+ long elapsed = -System.nanoTime();
+ ResponseAPDU response = cardManager.send(cmd);
+ elapsed += System.nanoTime();
+ return new Response.ECDSA(response, getDescription(), elapsed, keyPair, sigType, export, raw);
+ }
+
+ @Override
+ public String getDescription() {
+ String algo = CardUtil.getSigTypeString(sigType);
+ String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
+ String data = raw == null ? "random" : "provided";
+ return String.format("%s signature with %s keypair(%s data)", algo, key, data);
+ }
+ }
+
+ public static class ECDSA_verify extends Command {
+ private byte keyPair;
+ private byte sigType;
+ private byte[] raw;
+ private byte[] signature;
+
+ /**
+ * Creates the INS_ECDSA_VERIFY instruction.
+ *
+ * @param cardManager cardManager to send APDU through
+ * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
+ * @param sigType Signature type to use
+ * @param raw data to sign
+ * @param signature signature data
+ */
+ public ECDSA_verify(CardMngr cardManager, byte keyPair, byte sigType, byte[] raw, byte[] signature) {
+ super(cardManager);
+ if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
+ throw new IllegalArgumentException();
+ }
+ if (raw == null || signature == null) {
+ throw new IllegalArgumentException();
+ }
+
+ this.keyPair = keyPair;
+ this.sigType = sigType;
+ this.raw = raw;
+ this.signature = signature;
+
+ byte[] data = new byte[4 + raw.length + signature.length];
+ ByteUtil.setShort(data, 0, (short) raw.length);
+ System.arraycopy(raw, 0, data, 2, raw.length);
+ ByteUtil.setShort(data, 2 + raw.length, (short) signature.length);
+ System.arraycopy(signature, 0, data, 2 + raw.length + 2, signature.length);
+
+ this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA_VERIFY, keyPair, sigType, data);
+ }
+
+ @Override
+ public Response.ECDSA send() throws CardException {
+ long elapsed = -System.nanoTime();
+ ResponseAPDU response = cardManager.send(cmd);
+ elapsed += System.nanoTime();
+ return new Response.ECDSA(response, getDescription(), elapsed, keyPair, sigType, ECTesterApplet.EXPORT_FALSE, raw);
}
@Override
- public String toString() {
- return "ECDSA";
+ public String getDescription() {
+ String algo = CardUtil.getSigTypeString(sigType);
+ String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
+ String data = raw == null ? "random" : "provided";
+ return String.format("%s verification with %s keypair(%s data)", algo, key, data);
}
}
@@ -650,12 +856,12 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.Cleanup(response, elapsed);
+ return new Response.Cleanup(response, getDescription(), elapsed);
}
@Override
- public String toString() {
- return "Cleanup";
+ public String getDescription() {
+ return "Request JCSystem object deletion";
}
}
}
diff --git a/src/cz/crcs/ectester/reader/output/FileTestWriter.java b/src/cz/crcs/ectester/reader/output/FileTestWriter.java
new file mode 100644
index 0000000..e4ef9b8
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/output/FileTestWriter.java
@@ -0,0 +1,53 @@
+package cz.crcs.ectester.reader.output;
+
+import cz.crcs.ectester.common.output.TeeTestWriter;
+import cz.crcs.ectester.common.output.TestWriter;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.regex.Pattern;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class FileTestWriter extends TeeTestWriter {
+
+ private static final Pattern PREFIX = Pattern.compile("(text|xml|yaml|yml):.+");
+
+ public FileTestWriter(String defaultFormat, boolean systemOut, String[] files) throws ParserConfigurationException, FileNotFoundException {
+ int fLength = files == null ? 0 : files.length;
+ writers = new TestWriter[systemOut ? fLength + 1 : fLength];
+ if (systemOut) {
+ writers[0] = createWriter(defaultFormat, System.out);
+ }
+ for (int i = 0; i < fLength; ++i) {
+ String fName = files[i];
+ String format = null;
+ if (PREFIX.matcher(fName).matches()) {
+ String[] split = fName.split(":",2);
+ format = split[0];
+ fName = split[1];
+ }
+ writers[i + 1] = createWriter(format, new PrintStream(new FileOutputStream(fName)));
+ }
+ }
+
+ private TestWriter createWriter(String format, PrintStream out) throws ParserConfigurationException {
+ if (format == null) {
+ return new TextTestWriter(out);
+ }
+ switch (format) {
+ case "text":
+ return new TextTestWriter(out);
+ case "xml":
+ return new XMLTestWriter(out);
+ case "yaml":
+ case "yml":
+ return new YAMLTestWriter(out);
+ default:
+ return null;
+ }
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/output/TextTestWriter.java b/src/cz/crcs/ectester/reader/output/TextTestWriter.java
index eb52937..ad35012 100644
--- a/src/cz/crcs/ectester/reader/output/TextTestWriter.java
+++ b/src/cz/crcs/ectester/reader/output/TextTestWriter.java
@@ -1,10 +1,13 @@
package cz.crcs.ectester.reader.output;
+import cz.crcs.ectester.common.cli.Colors;
import cz.crcs.ectester.common.output.BaseTextTestWriter;
import cz.crcs.ectester.common.test.TestSuite;
import cz.crcs.ectester.common.test.Testable;
import cz.crcs.ectester.common.util.ByteUtil;
import cz.crcs.ectester.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
+import cz.crcs.ectester.reader.response.Response;
import cz.crcs.ectester.reader.test.CardTestSuite;
import cz.crcs.ectester.reader.test.CommandTestable;
@@ -27,7 +30,10 @@ public class TextTestWriter extends BaseTextTestWriter {
protected String testableString(Testable t) {
if (t instanceof CommandTestable) {
CommandTestable cmd = (CommandTestable) t;
- return writer.responseSuffix(cmd.getResponse());
+ Response response = cmd.getResponse();
+ if (response != null) {
+ return writer.responseSuffix(response);
+ }
}
return "";
}
@@ -37,11 +43,12 @@ public class TextTestWriter extends BaseTextTestWriter {
if (suite instanceof CardTestSuite) {
CardTestSuite cardSuite = (CardTestSuite) suite;
StringBuilder sb = new StringBuilder();
- sb.append("═══ Card ATR: ").append(ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false)).append(System.lineSeparator());
+ sb.append("═══ ").append(Colors.underline("ECTester version:")).append(" ").append(ECTesterReader.VERSION).append(ECTesterReader.GIT_COMMIT).append(System.lineSeparator());
+ sb.append("═══ ").append(Colors.underline("Card ATR:")).append(" ").append(ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false)).append(System.lineSeparator());
try {
CardMngr.CPLC cplc = cardSuite.getCard().getCPLC();
if (!cplc.values().isEmpty()) {
- sb.append("═══ Card CPLC data:").append(System.lineSeparator());
+ sb.append("═══ ").append(Colors.underline("Card CPLC data:")).append(System.lineSeparator());
for (Map.Entry<CardMngr.CPLC.Field, byte[]> entry : cplc.values().entrySet()) {
CardMngr.CPLC.Field field = entry.getKey();
byte[] value = entry.getValue();
diff --git a/src/cz/crcs/ectester/reader/output/XMLTestWriter.java b/src/cz/crcs/ectester/reader/output/XMLTestWriter.java
index d3674e8..00cc6c6 100644
--- a/src/cz/crcs/ectester/reader/output/XMLTestWriter.java
+++ b/src/cz/crcs/ectester/reader/output/XMLTestWriter.java
@@ -5,6 +5,7 @@ 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.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
import cz.crcs.ectester.reader.command.Command;
import cz.crcs.ectester.reader.response.Response;
import cz.crcs.ectester.reader.test.CardTestSuite;
@@ -26,16 +27,27 @@ public class XMLTestWriter extends BaseXMLTestWriter {
private Element commandElement(Command c) {
Element commandElem = doc.createElement("command");
+ if (c == null) {
+ return commandElem;
+ }
Element apdu = doc.createElement("apdu");
apdu.setTextContent(ByteUtil.bytesToHex(c.getAPDU().getBytes()));
commandElem.appendChild(apdu);
+ Element description = doc.createElement("desc");
+ description.setTextContent(c.getDescription());
+ commandElem.appendChild(description);
+
return commandElem;
}
private Element responseElement(Response r) {
Element responseElem = doc.createElement("response");
+ if (r == null) {
+ return responseElem;
+ }
+
responseElem.setAttribute("successful", r.successful() ? "true" : "false");
Element apdu = doc.createElement("apdu");
@@ -102,6 +114,7 @@ public class XMLTestWriter extends BaseXMLTestWriter {
CardTestSuite cardSuite = (CardTestSuite) suite;
Element result = doc.createElement("device");
result.setAttribute("type", "card");
+ result.setAttribute("ectester", ECTesterReader.VERSION + ECTesterReader.GIT_COMMIT);
result.appendChild(cplcElement(cardSuite.getCard()));
Element atr = doc.createElement("ATR");
diff --git a/src/cz/crcs/ectester/reader/output/YAMLTestWriter.java b/src/cz/crcs/ectester/reader/output/YAMLTestWriter.java
index 199f2c0..080fa8b 100644
--- a/src/cz/crcs/ectester/reader/output/YAMLTestWriter.java
+++ b/src/cz/crcs/ectester/reader/output/YAMLTestWriter.java
@@ -5,6 +5,7 @@ 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.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
import cz.crcs.ectester.reader.command.Command;
import cz.crcs.ectester.reader.response.Response;
import cz.crcs.ectester.reader.test.CardTestSuite;
@@ -12,10 +13,7 @@ import cz.crcs.ectester.reader.test.CommandTestable;
import javax.smartcardio.CardException;
import java.io.PrintStream;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -26,13 +24,20 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> commandObject(Command c) {
- Map<String, Object> commandObj = new HashMap<>();
+ Map<String, Object> commandObj = new LinkedHashMap<>();
+ if (c == null) {
+ return commandObj;
+ }
commandObj.put("apdu", ByteUtil.bytesToHex(c.getAPDU().getBytes()));
+ commandObj.put("desc", c.getDescription());
return commandObj;
}
private Map<String, Object> responseObject(Response r) {
- Map<String, Object> responseObj = new HashMap<>();
+ Map<String, Object> responseObj = new LinkedHashMap<>();
+ if (r == null) {
+ return responseObj;
+ }
responseObj.put("successful", r.successful());
responseObj.put("apdu", ByteUtil.bytesToHex(r.getAPDU().getBytes()));
responseObj.put("natural_sw", Short.toUnsignedInt(r.getNaturalSW()));
@@ -50,7 +55,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
protected Map<String, Object> testableObject(Testable t) {
if (t instanceof CommandTestable) {
CommandTestable cmd = (CommandTestable) t;
- Map<String, Object> result = new HashMap<>();
+ Map<String, Object> result = new LinkedHashMap<>();
result.put("type", "command");
result.put("command", commandObject(cmd.getCommand()));
result.put("response", responseObject(cmd.getResponse()));
@@ -60,7 +65,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> cplcObject(CardMngr card) {
- Map<String, Object> result = new HashMap<>();
+ Map<String, Object> result = new LinkedHashMap<>();
try {
CardMngr.CPLC cplc = card.getCPLC();
if (!cplc.values().isEmpty()) {
@@ -79,8 +84,9 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
protected Map<String, Object> deviceObject(TestSuite suite) {
if (suite instanceof CardTestSuite) {
CardTestSuite cardSuite = (CardTestSuite) suite;
- Map<String, Object> result = new HashMap<>();
+ Map<String, Object> result = new LinkedHashMap<>();
result.put("type", "card");
+ result.put("ectester", ECTesterReader.VERSION + ECTesterReader.GIT_COMMIT);
result.put("cplc", cplcObject(cardSuite.getCard()));
result.put("ATR", ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false));
return result;
diff --git a/src/cz/crcs/ectester/reader/response/Response.java b/src/cz/crcs/ectester/reader/response/Response.java
index cbed3b2..4814e41 100644
--- a/src/cz/crcs/ectester/reader/response/Response.java
+++ b/src/cz/crcs/ectester/reader/response/Response.java
@@ -3,9 +3,7 @@ package cz.crcs.ectester.reader.response;
import cz.crcs.ectester.applet.ECTesterApplet;
import cz.crcs.ectester.applet.EC_Consts;
import cz.crcs.ectester.common.util.ByteUtil;
-import cz.crcs.ectester.common.util.CardUtil;
import javacard.framework.ISO7816;
-import javacard.security.KeyPair;
import javax.smartcardio.ResponseAPDU;
@@ -20,9 +18,11 @@ public abstract class Response {
private byte[][] params;
private boolean success = true;
private boolean error = false;
+ private String description;
- public Response(ResponseAPDU response, long time) {
+ public Response(ResponseAPDU response, String description, long time) {
this.resp = response;
+ this.description = description;
this.time = time;
}
@@ -127,7 +127,9 @@ public abstract class Response {
return this.error;
}
- public abstract String getDescription();
+ public String getDescription() {
+ return description;
+ }
/**
*
@@ -135,17 +137,12 @@ public abstract class Response {
public static class AllocateKeyAgreement extends Response {
private byte kaType;
- public AllocateKeyAgreement(ResponseAPDU response, long time, byte kaType) {
- super(response, time);
+ public AllocateKeyAgreement(ResponseAPDU response, String description, long time, byte kaType) {
+ super(response, description, time);
this.kaType = kaType;
parse(1, 0);
}
-
- @Override
- public String getDescription() {
- return String.format("Allocated KeyAgreement(%s) object", CardUtil.getKATypeString(this.kaType));
- }
}
/**
@@ -154,17 +151,12 @@ public abstract class Response {
public static class AllocateSignature extends Response {
private byte sigType;
- public AllocateSignature(ResponseAPDU response, long time, byte sigType) {
- super(response, time);
+ public AllocateSignature(ResponseAPDU response, String description, long time, byte sigType) {
+ super(response, description, time);
this.sigType = sigType;
parse(1, 0);
}
-
- @Override
- public String getDescription() {
- return String.format("Allocated Signature(%s) object", CardUtil.getSigTypeString(this.sigType));
- }
}
/**
@@ -175,8 +167,8 @@ public abstract class Response {
private short keyLength;
private byte keyClass;
- public Allocate(ResponseAPDU response, long time, byte keyPair, short keyLength, byte keyClass) {
- super(response, time);
+ public Allocate(ResponseAPDU response, String description, long time, byte keyPair, short keyLength, byte keyClass) {
+ super(response, description, time);
this.keyPair = keyPair;
this.keyLength = keyLength;
this.keyClass = keyClass;
@@ -186,18 +178,6 @@ public abstract class Response {
if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++;
parse(pairs, 0);
}
-
- @Override
- public String getDescription() {
- String field = keyClass == KeyPair.ALG_EC_FP ? "ALG_EC_FP" : "ALG_EC_F2M";
- String key;
- if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
- key = "both keypairs";
- } else {
- key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
- }
- return String.format("Allocated %s %db %s", key, keyLength, field);
- }
}
/**
@@ -206,8 +186,8 @@ public abstract class Response {
public static class Clear extends Response {
private byte keyPair;
- public Clear(ResponseAPDU response, long time, byte keyPair) {
- super(response, time);
+ public Clear(ResponseAPDU response, String description, long time, byte keyPair) {
+ super(response, description, time);
this.keyPair = keyPair;
int pairs = 0;
@@ -215,17 +195,6 @@ public abstract class Response {
if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++;
parse(pairs, 0);
}
-
- @Override
- public String getDescription() {
- String key;
- if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
- key = "both keypairs";
- } else {
- key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
- }
- return String.format("Cleared %s", key);
- }
}
/**
@@ -236,8 +205,8 @@ public abstract class Response {
private byte curve;
private short parameters;
- public Set(ResponseAPDU response, long time, byte keyPair, byte curve, short parameters) {
- super(response, time);
+ public Set(ResponseAPDU response, String description, long time, byte keyPair, byte curve, short parameters) {
+ super(response, description, time);
this.keyPair = keyPair;
this.curve = curve;
this.parameters = parameters;
@@ -248,58 +217,23 @@ public abstract class Response {
parse(pairs, 0);
}
-
- @Override
- public String getDescription() {
- String name;
- switch (curve) {
- case EC_Consts.CURVE_default:
- name = "default";
- break;
- case EC_Consts.CURVE_external:
- name = "external";
- break;
- default:
- name = "custom";
- break;
- }
- String what = "";
- if (parameters == EC_Consts.PARAMETERS_DOMAIN_F2M || parameters == EC_Consts.PARAMETERS_DOMAIN_FP) {
- what = "curve";
- } else if (parameters == EC_Consts.PARAMETER_W) {
- what = "pubkey";
- } else if (parameters == EC_Consts.PARAMETER_S) {
- what = "privkey";
- } else if (parameters == EC_Consts.PARAMETERS_KEYPAIR) {
- what = "keypair";
- }
-
- String pair;
- if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
- pair = "both keypairs";
- } else {
- pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
- }
- return String.format("Set %s %s parameters on %s", name, what, pair);
- }
-
}
/**
*
*/
- public static class Corrupt extends Response {
+ public static class Transform extends Response {
private byte keyPair;
private byte key;
private short params;
- private byte corruption;
+ private short transformation;
- public Corrupt(ResponseAPDU response, long time, byte keyPair, byte key, short params, byte corruption) {
- super(response, time);
+ public Transform(ResponseAPDU response, String description, long time, byte keyPair, byte key, short params, short transformation) {
+ super(response, description, time);
this.keyPair = keyPair;
this.key = key;
this.params = params;
- this.corruption = corruption;
+ this.transformation = transformation;
int pairs = 0;
if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) pairs++;
@@ -307,19 +241,6 @@ public abstract class Response {
parse(pairs, 0);
}
-
- @Override
- public String getDescription() {
- String corrupt = CardUtil.getCorruption(corruption);
-
- String pair;
- if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
- pair = "both keypairs";
- } else {
- pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
- }
- return String.format("Corrupted params of %s, %s", pair, corrupt);
- }
}
/**
@@ -328,8 +249,8 @@ public abstract class Response {
public static class Generate extends Response {
private byte keyPair;
- public Generate(ResponseAPDU response, long time, byte keyPair) {
- super(response, time);
+ public Generate(ResponseAPDU response, String description, long time, byte keyPair) {
+ super(response, description, time);
this.keyPair = keyPair;
int generated = 0;
@@ -337,18 +258,6 @@ public abstract class Response {
if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) generated++;
parse(generated, 0);
}
-
- @Override
- public String getDescription() {
- String key;
- if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
- key = "both keypairs";
- } else {
- key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
- }
- return String.format("Generated %s", key);
- }
-
}
/**
@@ -359,8 +268,8 @@ public abstract class Response {
private byte key;
private short parameters;
- public Export(ResponseAPDU response, long time, byte keyPair, byte key, short parameters) {
- super(response, time);
+ public Export(ResponseAPDU response, String description, long time, byte keyPair, byte key, short parameters) {
+ super(response, description, time);
this.keyPair = keyPair;
this.key = key;
this.parameters = parameters;
@@ -440,23 +349,6 @@ public abstract class Response {
public byte[] getParameter(byte keyPair, short param) {
return getParam(getIndex(keyPair, param));
}
-
- @Override
- public String getDescription() {
- String source;
- if (key == EC_Consts.KEY_BOTH) {
- source = "both keys";
- } else {
- source = ((key == EC_Consts.KEY_PUBLIC) ? "public" : "private") + " key";
- }
- String pair;
- if (keyPair == ECTesterApplet.KEYPAIR_BOTH) {
- pair = "both keypairs";
- } else {
- pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair";
- }
- return String.format("Exported params from %s of %s", source, pair);
- }
}
/**
@@ -466,15 +358,15 @@ public abstract class Response {
private byte pubkey;
private byte privkey;
private byte export;
- private short corruption;
+ private short transformation;
private byte type;
- public ECDH(ResponseAPDU response, long time, byte pubkey, byte privkey, byte export, short corruption, byte type) {
- super(response, time);
+ public ECDH(ResponseAPDU response, String description, long time, byte pubkey, byte privkey, byte export, short transformation, byte type) {
+ super(response, description, time);
this.pubkey = pubkey;
this.privkey = privkey;
this.export = export;
- this.corruption = corruption;
+ this.transformation = transformation;
this.type = type;
parse(1, (export == ECTesterApplet.EXPORT_TRUE) ? 1 : 0);
@@ -491,22 +383,6 @@ public abstract class Response {
public int secretLength() {
return getParamLength(0);
}
-
- @Override
- public String getDescription() {
- String algo = CardUtil.getKATypeString(type);
-
- String pub = pubkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
- String priv = privkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
-
- String validity;
- if (corruption == EC_Consts.CORRUPTION_NONE) {
- validity = "unchanged";
- } else {
- validity = CardUtil.getCorruption(corruption);
- }
- return String.format("%s of %s pubkey and %s privkey(%s point)", algo, pub, priv, validity);
- }
}
/**
@@ -518,8 +394,8 @@ public abstract class Response {
private byte export;
private byte[] raw;
- public ECDSA(ResponseAPDU response, long time, byte keyPair, byte sigType, byte export, byte[] raw) {
- super(response, time);
+ public ECDSA(ResponseAPDU response, String description, long time, byte keyPair, byte sigType, byte export, byte[] raw) {
+ super(response, description, time);
this.keyPair = keyPair;
this.sigType = sigType;
this.export = export;
@@ -535,14 +411,6 @@ public abstract class Response {
public byte[] getSignature() {
return getParam(0);
}
-
- @Override
- public String getDescription() {
- String algo = CardUtil.getSigTypeString(sigType);
- String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
- String data = raw == null ? "random" : "provided";
- return String.format("%s with %s keypair(%s data)", algo, key, data);
- }
}
/**
@@ -550,16 +418,10 @@ public abstract class Response {
*/
public static class Cleanup extends Response {
- public Cleanup(ResponseAPDU response, long time) {
- super(response, time);
+ public Cleanup(ResponseAPDU response, String description, long time) {
+ super(response, description, time);
parse(1, 0);
}
-
- @Override
- public String getDescription() {
- return "Requested JCSystem object deletion";
- }
-
}
}
diff --git a/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java
new file mode 100644
index 0000000..39024b8
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java
@@ -0,0 +1,77 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+import cz.crcs.ectester.common.ec.EC_Key;
+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.data.EC_Store;
+import cz.crcs.ectester.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
+import cz.crcs.ectester.reader.command.Command;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import static cz.crcs.ectester.common.test.Result.ExpectedValue;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardCofactorSuite extends CardTestSuite {
+ public CardCofactorSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ 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 during ECDH.");
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "cofactor");
+ List<Map.Entry<EC_Curve, List<EC_Key.Public>>> curveList = EC_Store.mapKeyToCurve(pubkeys.values());
+ for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList) {
+ EC_Curve curve = e.getKey();
+ List<EC_Key.Public> keys = e.getValue();
+
+ Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS);
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS);
+ Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.SUCCESS);
+
+ Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate);
+
+ List<Test> ecdhTests = new LinkedList<>();
+ for (EC_Key.Public pub : keys) {
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
+ ecdhTests.add(CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on non-generator subgroup.", "Card incorrectly accepted point on non-generator subgroup."));
+ }
+ Test ecdh = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH with public points on non-generator subgroup.", ecdhTests.toArray(new Test[0]));
+
+ Random r = new Random();
+ byte[] raw = new byte[128];
+ byte[] sig = new byte[40];
+ r.nextBytes(raw);
+ r.nextBytes(sig);
+
+ List<Test> ecdsaTests = new LinkedList<>();
+ for (EC_Key.Public pub : keys) {
+ Command setCommand = new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten());
+ Test setTest = CommandTest.expect(setCommand, ExpectedValue.ANY);
+ Command ecdsaCommand = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.Signature_ALG_ECDSA_SHA, raw, sig);
+ Test ecdsaTest = CommandTest.expect(ecdsaCommand, ExpectedValue.FAILURE);
+ ecdsaTests.add(CompoundTest.all(ExpectedValue.SUCCESS, "Verify random ECDSA signature by " + pub.getId() + ".", setTest, ecdsaTest));
+ }
+ Test ecdsa = CompoundTest.all(ExpectedValue.SUCCESS, "Verify random ECDSA signature by public points on non-generator subgroup.", ecdsaTests.toArray(new Test[0]));
+
+ Test tests = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH and ECDSA tests.", ecdh, ecdsa);
+
+ if (cfg.cleanup) {
+ Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.SUCCESS);
+ doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Cofactor test of " + curve.getId() + ".", prepare, tests, cleanup));
+ } else {
+ doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Cofactor test of " + curve.getId() + ".", prepare, tests));
+ }
+ }
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java
deleted file mode 100644
index a53806c..0000000
--- a/src/cz/crcs/ectester/reader/test/CardCompositeCurvesSuite.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package cz.crcs.ectester.reader.test;
-
-import cz.crcs.ectester.applet.ECTesterApplet;
-import cz.crcs.ectester.applet.EC_Consts;
-import cz.crcs.ectester.common.ec.EC_Curve;
-import cz.crcs.ectester.common.ec.EC_Key;
-import cz.crcs.ectester.common.output.TestWriter;
-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 javacard.security.KeyPair;
-
-import java.util.Map;
-
-import static cz.crcs.ectester.common.test.Result.ExpectedValue;
-
-/**
- * @author Jan Jancar johny@neuromancer.sk
- */
-public class CardCompositeCurvesSuite extends CardTestSuite {
-
- public CardCompositeCurvesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "composite", "The composite suite run ECDH over curves with composite order. This should generally fail, as using such a curve is unsafe.");
- }
-
- @Override
- protected void runTests() throws Exception {
- /* Do the default run with the public keys set to provided smallorder keys
- * over composite order curves. Essentially small subgroup attacks.
- * These should fail, the curves aren't safe so that if the computation with
- * a small order public key succeeds the private key modulo the public key order
- * is revealed.
- */
- Map<String, EC_Key> keys = EC_Store.getInstance().getObjects(EC_Key.class, "composite");
- for (EC_Key key : keys.values()) {
- EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, key.getCurve());
- if (curve.getField() == KeyPair.ALG_EC_FP && !cfg.primeField || curve.getField() == KeyPair.ALG_EC_F2M && !cfg.binaryField) {
- continue;
- }
- if ((curve.getBits() == cfg.bits || cfg.all)) {
- doTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS));
- doTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY));
- doTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.ANY));
- Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH, key.flatten());
- doTest(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."));
- new Command.Cleanup(this.card).send();
- }
- }
- }
-}
diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java
new file mode 100644
index 0000000..ec56901
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java
@@ -0,0 +1,116 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+import cz.crcs.ectester.common.ec.EC_Key;
+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.data.EC_Store;
+import cz.crcs.ectester.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
+import cz.crcs.ectester.reader.command.Command;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static cz.crcs.ectester.common.test.Result.ExpectedValue;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardCompositeSuite extends CardTestSuite {
+
+ public CardCompositeSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ super(writer, cfg, cardManager, "composite", "The composite suite runs ECDH over curves with composite order. This should generally fail, as using such a curve is unsafe.");
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ /* Do the default run with the public keys set to provided smallorder keys
+ * over composite order curves. Essentially small subgroup attacks.
+ * These should fail, the curves aren't safe so that if the computation with
+ * a small order public key succeeds the private key modulo the public key order
+ * is revealed.
+ */
+ Map<String, EC_Key> keys = EC_Store.getInstance().getObjects(EC_Key.class, "composite");
+ List<Map.Entry<EC_Curve, List<EC_Key>>> mappedKeys = EC_Store.mapKeyToCurve(keys.values());
+ for (Map.Entry<EC_Curve, List<EC_Key>> curveKeys : mappedKeys) {
+ EC_Curve curve = curveKeys.getKey();
+ List<Test> tests = new LinkedList<>();
+ Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS));
+ if (!allocate.ok()) {
+ doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocate));
+ continue;
+ }
+ tests.add(allocate);
+ tests.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY));
+ tests.add(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.ANY));
+ for (EC_Key key : curveKeys.getValue()) {
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.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() + ", " + key.getDesc(), ecdh));
+ }
+ doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ".", tests.toArray(new Test[0])));
+ }
+
+
+ Map<String, EC_Curve> results = EC_Store.getInstance().getObjects(EC_Curve.class, "composite");
+ List<Map.Entry<String, List<EC_Curve>>> groupList = EC_Store.mapToPrefix(results.values());
+ /* Test the whole curves with both keypairs generated on card(no small-order public points provided).
+ */
+ List<EC_Curve> wholeCurves = groupList.stream().filter((e) -> e.getKey().equals("whole")).findFirst().get().getValue();
+ testGroup(wholeCurves, "Composite generator order", ExpectedValue.FAILURE, "Card rejected to do ECDH with composite order generator.", "Card did not reject to do ECDH with composite order generator.");
+
+ /* Also test having a G of small order, so small R.
+ */
+ List<EC_Curve> smallRCurves = groupList.stream().filter((e) -> e.getKey().equals("small")).findFirst().get().getValue();
+ testGroup(smallRCurves, "Small generator order", ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a small order generator.", "Card incorrectly does ECDH over a small order generator.");
+
+ /* Test increasingly larger prime R, to determine where/if card behavior changes.
+ */
+ List<EC_Curve> varyingCurves = groupList.stream().filter((e) -> e.getKey().equals("varying")).findFirst().get().getValue();
+ testGroup(varyingCurves, null, ExpectedValue.ANY, "", "");
+
+ /* Also test having a G of large but composite order, R = p * q,
+ */
+ List<EC_Curve> pqCurves = groupList.stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue();
+ testGroup(pqCurves, null, ExpectedValue.ANY, "", "");
+
+ /* Also test having G or large order being a Carmichael pseudoprime, R = p * q * r,
+ */
+ List<EC_Curve> ppCurves = groupList.stream().filter((e) -> e.getKey().equals("pp")).findFirst().get().getValue();
+ testGroup(ppCurves, "Generator order = Carmichael pseudoprime", ExpectedValue.ANY, "", "");
+
+ /* Also test rg0 curves.
+ */
+ List<EC_Curve> rg0Curves = groupList.stream().filter((e) -> e.getKey().equals("rg0")).findFirst().get().getValue();
+ testGroup(rg0Curves, null, ExpectedValue.ANY, "", "");
+ }
+
+ private void testGroup(List<EC_Curve> curves, String testName, ExpectedValue dhValue, String ok, String nok) throws Exception {
+ for (EC_Curve curve : curves) {
+ Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS);
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY);
+ Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.ANY);
+ Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), dhValue, ok, nok);
+
+ String description;
+ if (testName == null) {
+ description = curve.getDesc() + " test of " + curve.getId() + ".";
+ } else {
+ description = testName + " test of " + curve.getId() + ".";
+ }
+ if (cfg.cleanup) {
+ Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.SUCCESS);
+ doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, description, allocate, set, generate, ecdh, cleanup));
+ } else {
+ doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, description, allocate, set, generate, ecdh));
+ }
+ }
+
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java
new file mode 100644
index 0000000..5e8f600
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java
@@ -0,0 +1,122 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.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.ByteUtil;
+import cz.crcs.ectester.common.util.CardUtil;
+import cz.crcs.ectester.common.util.ECUtil;
+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 javacard.security.KeyPair;
+
+import java.security.spec.ECPoint;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardCompressionSuite extends CardTestSuite {
+ public CardCompressionSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ super(writer, cfg, cardManager, "compression", "The compression test suite tests cards support for compressed points in ECDH (as per ANSI X9.62).",
+ "It also tests for handling of bogus input by using the point at infinity and a hybrid point with the y coordinate corrupted.");
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ //iterate over default curve sizes
+ // for Fp
+ // - allocate, set custom curve, generate keypairs, -> export generated.
+ // - test ecdh with local and remote simply(no compression)
+ // - test local privkey, remote pubkey (compressed)
+ // - test local privkey, remote pubkey (hybrid)
+ // - test local privkey, remote pubkey (hybrid with wrong y)
+ // - test local privkey, remote pubkey (point at infinity)
+ if (cfg.primeField) {
+ runCompression(KeyPair.ALG_EC_FP);
+ }
+ // for F2m
+ // - allocate, set custom curve, generate keypairs, -> export generated.
+ // - test ecdh with local and remote simply(no compression)
+ // - test local privkey, remote pubkey (compressed)
+ // - test local privkey, remote pubkey (hybrid)
+ // - test local privkey, remote pubkey (hybrid with wrong y)
+ // - test local privkey, remote pubkey (point at infinity)
+ if (cfg.binaryField) {
+ runCompression(KeyPair.ALG_EC_F2M);
+ }
+ }
+
+ private void runCompression(byte field) throws Exception {
+ short[] keySizes = field == KeyPair.ALG_EC_FP ? EC_Consts.FP_SIZES : EC_Consts.F2M_SIZES;
+ short domain = field == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M;
+
+ for (short keyLength : keySizes) {
+ String spec = keyLength + "b " + CardUtil.getKeyTypeString(field);
+
+ Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, field), Result.ExpectedValue.SUCCESS));
+ if (!allocateFirst.ok()) {
+ doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + spec + ".", allocateFirst));
+ continue;
+ }
+
+ List<Test> compressionTests = new LinkedList<>();
+ compressionTests.add(allocateFirst);
+ Test setCustom = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.getCurve(keyLength, field), domain, null), Result.ExpectedValue.SUCCESS));
+ Test genCustom = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.SUCCESS));
+ compressionTests.add(setCustom);
+ compressionTests.add(genCustom);
+
+ Response.Export key = new Command.Export(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W).send();
+ byte[] pubkey = key.getParameter(ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC);
+ ECPoint pub;
+ try {
+ pub = ECUtil.fromX962(pubkey, null);
+ } catch (IllegalArgumentException iae) {
+ // TODO: use external SECG curves so we have them here.
+ doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "", compressionTests.toArray(new Test[0])));
+ continue;
+ }
+
+ List<Test> kaTests = new LinkedList<>();
+ for (byte kaType : EC_Consts.KA_TYPES) {
+ List<Test> thisTests = new LinkedList<>();
+ Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), Result.ExpectedValue.SUCCESS));
+ if (allocate.ok()) {
+ Test ka = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType), Result.ExpectedValue.SUCCESS));
+
+ thisTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyAgreement setup and basic test.", allocate, ka));
+ if (ka.ok()) {
+ // tests of the good stuff
+ Test kaCompressed = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_COMPRESS, kaType), Result.ExpectedValue.SUCCESS);
+ Test kaHybrid = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_COMPRESS_HYBRID, kaType), Result.ExpectedValue.SUCCESS);
+ thisTests.add(CompoundTest.any(Result.ExpectedValue.SUCCESS, "Tests of compressed and hybrid form.", kaCompressed, kaHybrid));
+
+ // tests the bad stuff here
+ byte[] pubHybrid = ECUtil.toX962Hybrid(pub, keyLength);
+ pubHybrid[pubHybrid.length - 1] ^= 1;
+ byte[] pubHybridEncoded = ByteUtil.prependLength(pubHybrid);
+ Test kaBadHybrid = CommandTest.expect(new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType, pubHybridEncoded), Result.ExpectedValue.FAILURE);
+
+ byte[] pubInfinityEncoded = {0x01, 0x00};
+ Test kaBadInfinity = CommandTest.expect(new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType, pubInfinityEncoded), Result.ExpectedValue.FAILURE);
+ thisTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests of corrupted hybrid form and infinity.", kaBadHybrid, kaBadInfinity));
+ }
+ kaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyAgreement tests of " + CardUtil.getKATypeString(kaType) + ".", thisTests.toArray(new Test[0])));
+ }
+ }
+ compressionTests.addAll(kaTests);
+ if (cfg.cleanup) {
+ compressionTests.add(CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.SUCCESS));
+ }
+
+ doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Compression test of " + spec + ".", compressionTests.toArray(new Test[0])));
+ }
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java
index c3bd9c8..fa9bfd0 100644
--- a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java
@@ -4,6 +4,7 @@ import cz.crcs.ectester.applet.ECTesterApplet;
import cz.crcs.ectester.applet.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.reader.CardMngr;
@@ -13,8 +14,13 @@ import javacard.security.KeyPair;
import java.util.LinkedList;
import java.util.List;
+import java.util.Random;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static cz.crcs.ectester.common.test.Result.ExpectedValue;
+import static cz.crcs.ectester.common.test.Result.Value;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -22,7 +28,7 @@ import static cz.crcs.ectester.common.test.Result.ExpectedValue;
public class CardDefaultSuite extends CardTestSuite {
public CardDefaultSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "default", "The default test suite run basic support of ECDH and ECDSA.");
+ super(writer, cfg, cardManager, "default", "The default test suite tests basic support of ECDH and ECDSA.");
}
@Override
@@ -37,58 +43,99 @@ public class CardDefaultSuite extends CardTestSuite {
private void runDefault(byte field) throws Exception {
short[] keySizes = field == KeyPair.ALG_EC_FP ? EC_Consts.FP_SIZES : EC_Consts.F2M_SIZES;
+ short domain = field == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M;
for (short keyLength : keySizes) {
- String description = "Tests of " + keyLength + "b " + (field == KeyPair.ALG_EC_FP ? "ALG_EC_FP" : "ALG_EC_F2M") + " support.";
List<Test> supportTests = new LinkedList<>();
- Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, field), ExpectedValue.SUCCESS));
- if (!key.ok()) {
- doTest(CompoundTest.all(ExpectedValue.SUCCESS, description + " None.", key));
+ Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, field), ExpectedValue.SUCCESS));
+ if (!allocateFirst.ok()) {
+ doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + keyLength + "b " + CardUtil.getKeyTypeString(field) + ".", allocateFirst));
continue;
}
- supportTests.add(key);
+ supportTests.add(allocateFirst);
Test genDefault = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.SUCCESS));
- Test setCustom = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.getCurve(keyLength, field), EC_Consts.PARAMETERS_DOMAIN_FP, null), ExpectedValue.SUCCESS));
+ Test allocateSecond = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, field), ExpectedValue.SUCCESS));
+ Test setCustom = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.getCurve(keyLength, field), domain, null), ExpectedValue.SUCCESS));
Test genCustom = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.SUCCESS));
supportTests.add(genDefault);
+ supportTests.add(allocateSecond);
supportTests.add(setCustom);
supportTests.add(genCustom);
+ List<Test> kaTests = new LinkedList<>();
for (byte kaType : EC_Consts.KA_TYPES) {
Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), ExpectedValue.SUCCESS));
if (allocate.ok()) {
- Command ecdh = new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, kaType);
+ Command ecdh = new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType);
Test ka = runTest(CommandTest.expect(ecdh, ExpectedValue.SUCCESS));
- Test kaCompressed = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_COMPRESS, kaType), ExpectedValue.SUCCESS));
- Test perfTest = null;
+ Test kaCompressed = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_COMPRESS, kaType), ExpectedValue.SUCCESS));
+
+ String kaDesc = "Test of the " + CardUtil.getKATypeString(kaType) + " KeyAgreement.";
+ Function<Test[], Result> kaCallback = (tests) -> {
+ if (tests[1].ok() || tests[2].ok()) {
+ return new Result(Value.SUCCESS, "Some ECDH is supported.");
+ } else {
+ return new Result(Value.FAILURE, "ECDH failed.");
+ }
+ };
+
+ Test compound;
if (ka.ok()) {
- perfTest = runTest(PerformanceTest.repeat(ecdh, 10));
+ Test perfTest = runTest(PerformanceTest.repeat(ecdh, 10));
+ compound = runTest(CompoundTest.function(kaCallback, kaDesc, allocate, ka, kaCompressed, perfTest));
+ } else {
+ compound = runTest(CompoundTest.function(kaCallback, kaDesc, allocate, ka, kaCompressed));
}
- Test compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, "Test of the " + CardUtil.getKATypeString(kaType) + " KeyAgreement.", allocate, ka, kaCompressed, perfTest));
- supportTests.add(compound);
+
+ kaTests.add(compound);
} else {
runTest(allocate);
- supportTests.add(allocate);
+ kaTests.add(allocate);
}
}
+ Test kaTest = runTest(CompoundTest.any(ExpectedValue.SUCCESS, "KeyAgreement tests.", kaTests.toArray(new Test[0])));
+ supportTests.add(kaTest);
+
+ List<Test> signTests = new LinkedList<>();
for (byte sigType : EC_Consts.SIG_TYPES) {
Test allocate = runTest(CommandTest.expect(new Command.AllocateSignature(this.card, sigType), ExpectedValue.SUCCESS));
if (allocate.ok()) {
Command ecdsa = new Command.ECDSA(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, ECTesterApplet.EXPORT_FALSE, null);
Test expect = runTest(CommandTest.expect(ecdsa, ExpectedValue.SUCCESS));
- Test perfTest = null;
+
+ String signDesc = "Test of the " + CardUtil.getSigTypeString(sigType) + " signature.";
+
+ Random rand = new Random();
+ byte[] sigData = new byte[64];
+ rand.nextBytes(sigData);
+
+ Test compound;
if (expect.ok()) {
- perfTest = runTest(PerformanceTest.repeat(ecdsa, 10));
+ Command ecdsaSign = new Command.ECDSA_sign(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, ECTesterApplet.EXPORT_TRUE, sigData);
+ PerformanceTest signTest = runTest(PerformanceTest.repeat("Sign", ecdsaSign, 10));
+ byte[] signature = signTest.getResponses()[0].getParam(0);
+ Command ecdsaVerify = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, sigData, signature);
+ PerformanceTest verifyTest = runTest(PerformanceTest.repeat("Verify", ecdsaVerify, 10));
+ compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, signDesc, allocate, expect, signTest, verifyTest));
+ } else {
+ compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, signDesc, allocate, expect));
}
- Test compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, "Test of the " + CardUtil.getSigTypeString(sigType) + " signature.", allocate, expect, perfTest));
- supportTests.add(compound);
+ signTests.add(compound);
} else {
- supportTests.add(allocate);
+ signTests.add(allocate);
}
}
- doTest(CompoundTest.all(ExpectedValue.SUCCESS, description + " Some.", supportTests.toArray(new Test[0])));
- new Command.Cleanup(this.card).send();
+ Test signTest = runTest(CompoundTest.any(ExpectedValue.SUCCESS, "Signature tests.", signTests.toArray(new Test[0])));
+ supportTests.add(signTest);
+ ExpectedValue[] testExpects = {ExpectedValue.SUCCESS, ExpectedValue.ANY, ExpectedValue.SUCCESS, ExpectedValue.SUCCESS, ExpectedValue.SUCCESS, ExpectedValue.SUCCESS, ExpectedValue.SUCCESS};
+ List<ExpectedValue> expects = Stream.of(testExpects).collect(Collectors.toList());
+ if (cfg.cleanup) {
+ supportTests.add(CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.SUCCESS));
+ expects.add(ExpectedValue.ANY);
+ }
+
+ doTest(CompoundTest.mask(expects.toArray(new ExpectedValue[0]), "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(field) + " support.", supportTests.toArray(new Test[0])));
}
}
}
diff --git a/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java
new file mode 100644
index 0000000..064c6cb
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java
@@ -0,0 +1,59 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+import cz.crcs.ectester.common.ec.EC_Key;
+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.data.EC_Store;
+import cz.crcs.ectester.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
+import cz.crcs.ectester.reader.command.Command;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardDegenerateSuite extends CardTestSuite {
+
+ public CardDegenerateSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ 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 work.");
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "degenerate");
+ List<Map.Entry<EC_Curve, List<EC_Key.Public>>> curveList = EC_Store.mapKeyToCurve(pubkeys.values());
+ for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList) {
+ EC_Curve curve = e.getKey();
+ List<EC_Key.Public> keys = e.getValue();
+
+ Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS);
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS);
+ Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS);
+
+ Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate);
+
+ List<Test> ecdhTests = new LinkedList<>();
+ for (EC_Key.Public pub : keys) {
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
+ ecdhTests.add(CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve."));
+ }
+ Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with degenerate public points", ecdhTests.toArray(new Test[0]));
+ if (cfg.cleanup) {
+ Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.SUCCESS);
+ doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId(), prepare, ecdh, cleanup));
+ } else {
+ doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId(), prepare, ecdh));
+ }
+
+ }
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java
new file mode 100644
index 0000000..dc489a0
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java
@@ -0,0 +1,189 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+import cz.crcs.ectester.common.ec.EC_KAResult;
+import cz.crcs.ectester.common.ec.EC_Key;
+import cz.crcs.ectester.common.ec.EC_Params;
+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.test.TestCallback;
+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.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
+import cz.crcs.ectester.reader.command.Command;
+import cz.crcs.ectester.reader.response.Response;
+import javacard.security.CryptoException;
+import javacard.security.KeyPair;
+
+import java.math.BigInteger;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardEdgeCasesSuite extends CardTestSuite {
+ public CardEdgeCasesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ 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.",
+ "Various edge private key values are also tested.");
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ Map<String, EC_KAResult> results = EC_Store.getInstance().getObjects(EC_KAResult.class, "wycheproof");
+ List<Map.Entry<String, List<EC_KAResult>>> groupList = EC_Store.mapToPrefix(results.values());
+ for (Map.Entry<String, List<EC_KAResult>> e : groupList) {
+ String description = null;
+ switch (e.getKey()) {
+ case "addsub":
+ description = "Tests for addition-subtraction chains.";
+ break;
+ case "cve_2017_10176":
+ description = "Tests for CVE-2017-10176.";
+ break;
+ case "cve_2017_8932":
+ description = "Tests for CVE-2017-8932.";
+ break;
+ }
+
+ List<Test> groupTests = new LinkedList<>();
+ List<Map.Entry<EC_Curve, List<EC_KAResult>>> curveList = EC_Store.mapResultToCurve(e.getValue());
+ for (Map.Entry<EC_Curve, List<EC_KAResult>> c : curveList) {
+ EC_Curve curve = c.getKey();
+
+ List<Test> curveTests = new LinkedList<>();
+ Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS);
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS);
+ Test prepareCurve = CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Prepare curve", allocate, set);
+
+ List<EC_KAResult> values = c.getValue();
+ for (EC_KAResult value : values) {
+ String id = value.getId();
+ String privkeyId = value.getOneKey();
+ String pubkeyId = value.getOtherKey();
+
+ EC_Key.Private privkey = EC_Store.getInstance().getObject(EC_Key.Private.class, privkeyId);
+ EC_Key.Public pubkey = EC_Store.getInstance().getObject(EC_Key.Public.class, pubkeyId);
+
+ Test setPrivkey = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, privkey.getParams(), privkey.flatten()), Result.ExpectedValue.SUCCESS);
+ Test setPubkey = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pubkey.getParams(), pubkey.flatten()), Result.ExpectedValue.SUCCESS);
+ Test ecdhPreTest = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.SUCCESS);
+ Test ecdh = CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, value.getJavaCardKA()), new TestCallback<CommandTestable>() {
+ @Override
+ public Result apply(CommandTestable testable) {
+ Response.ECDH dh = (Response.ECDH) testable.getResponse();
+ if (dh.getSW(0) == CryptoException.NO_SUCH_ALGORITHM) {
+ return new Result(Result.Value.SUCCESS, "ECDH algorithm unsupported.");
+ }
+ if (!dh.successful())
+ return new Result(Result.Value.FAILURE, "ECDH was unsuccessful.");
+ if (!dh.hasSecret())
+ return new Result(Result.Value.FAILURE, "ECDH response did not contain the derived secret.");
+ if (!ByteUtil.compareBytes(dh.getSecret(), 0, value.getData(0), 0, dh.secretLength())) {
+ int firstDiff = ByteUtil.diffBytes(dh.getSecret(), 0, value.getData(0), 0, dh.secretLength());
+ System.err.println(ByteUtil.bytesToHex(dh.getSecret()));
+ System.err.println(ByteUtil.bytesToHex(value.getData(0)));
+ return new Result(Result.Value.FAILURE, "ECDH derived secret does not match the test-vector, first difference was at byte " + String.valueOf(firstDiff) + ".");
+ }
+ return new Result(Result.Value.SUCCESS);
+ }
+ });
+
+ Test prepare = CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Prepare", setPrivkey, setPubkey);
+ Test ka = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do", ecdhPreTest, ecdh);
+
+ Test one = CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Test " + id + ".", prepare, ka);
+ curveTests.add(one);
+ }
+
+ Test curveTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests", curveTests.toArray(new Test[0]));
+ groupTests.add(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Tests on " + curve.getId() + ".", prepareCurve, curveTest));
+ }
+ doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, description, groupTests.toArray(new Test[0])));
+ }
+
+ 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() == KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList());
+ Random rand = new Random();
+ for (EC_Curve curve : curves) {
+ Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), KeyPair.ALG_EC_FP), Result.ExpectedValue.SUCCESS));
+ if (!key.ok()) {
+ doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b ALG_EC_FP.", key));
+ continue;
+ }
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS);
+ Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS);
+ Test setup = CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyPair setup.", key, set, generate);
+
+ Test zeroS = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, EC_Consts.TRANSFORMATION_ZERO), "ECDH with S = 0.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE);
+ Test oneS = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, EC_Consts.TRANSFORMATION_ONE), "ECDH with S = 1.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE);
+
+ byte[] r = curve.getParam(EC_Consts.PARAMETER_R)[0];
+ BigInteger R = new BigInteger(1, r);
+ BigInteger smaller = new BigInteger(curve.getBits(), rand).mod(R);
+ BigInteger diff = R.divide(BigInteger.valueOf(10));
+ BigInteger randDiff = new BigInteger(diff.bitLength(), rand).mod(diff);
+ BigInteger larger = R.add(randDiff);
+
+ EC_Params smallerParams = makeParams(smaller);
+ Test smallerS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, smallerParams.getParams(), smallerParams.flatten()), "ECDH with S < r.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS);
+
+ EC_Params exactParams = makeParams(R);
+ Test exactS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, exactParams.getParams(), exactParams.flatten()), "ECDH with S = r.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE);
+
+ EC_Params largerParams = makeParams(larger);
+ Test largerS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, largerParams.getParams(), largerParams.flatten()), "ECDH with S > r.", Result.ExpectedValue.ANY, Result.ExpectedValue.ANY);
+
+ BigInteger rm1 = R.subtract(BigInteger.ONE);
+ BigInteger rp1 = R.add(BigInteger.ONE);
+
+ EC_Params rm1Params = makeParams(rm1);
+ Test rm1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, rm1Params.getParams(), rm1Params.flatten()), "ECDH with S = r - 1.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS);
+
+ EC_Params rp1Params = makeParams(rp1);
+ Test rp1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, rp1Params.getParams(), rp1Params.flatten()), "ECDH with S = r + 1.", Result.ExpectedValue.ANY, Result.ExpectedValue.ANY);
+
+ byte[] k = curve.getParam(EC_Consts.PARAMETER_K)[0];
+ BigInteger K = new BigInteger(1, k);
+ BigInteger kr = K.multiply(R);
+ BigInteger krm1 = kr.subtract(BigInteger.ONE);
+ BigInteger krp1 = kr.add(BigInteger.ONE);
+
+ EC_Params krParams = makeParams(kr);
+ Test krS /*ONE!*/ = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krParams.getParams(), krParams.flatten()), "ECDH with S = k * r.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE);
+
+ EC_Params krm1Params = makeParams(krm1);
+ Test krm1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krm1Params.getParams(), krm1Params.flatten()), "ECDH with S = (k * r) - 1.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE);
+
+ EC_Params krp1Params = makeParams(krp1);
+ Test krp1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krp1Params.getParams(), krp1Params.flatten()), "ECDH with S = (k * r) + 1.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE);
+
+ doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with edge-case private key values over " + curve.getId() + ".", setup, zeroS, oneS, smallerS, exactS, largerS, rm1S, rp1S, krS, krm1S, krp1S));
+ }
+ }
+
+ private Test ecdhTest(Command setPriv, String desc, Result.ExpectedValue setExpect, Result.ExpectedValue ecdhExpect) {
+ Test set = CommandTest.expect(setPriv, setExpect);
+ Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ecdhExpect);
+
+ return CompoundTest.any(Result.ExpectedValue.SUCCESS, desc, set, ecdh);
+ }
+
+ private EC_Params makeParams(BigInteger s) {
+ return makeParams(ECUtil.toByteArray(s, s.bitLength()));
+ }
+
+ private EC_Params makeParams(byte[] s) {
+ return new EC_Params(EC_Consts.PARAMETER_S, new byte[][]{s});
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java
deleted file mode 100644
index 8424d45..0000000
--- a/src/cz/crcs/ectester/reader/test/CardInvalidCurvesSuite.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package cz.crcs.ectester.reader.test;
-
-import cz.crcs.ectester.applet.ECTesterApplet;
-import cz.crcs.ectester.applet.EC_Consts;
-import cz.crcs.ectester.common.ec.EC_Curve;
-import cz.crcs.ectester.common.ec.EC_Key;
-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.data.EC_Store;
-import cz.crcs.ectester.reader.CardMngr;
-import cz.crcs.ectester.reader.ECTesterReader;
-import cz.crcs.ectester.reader.command.Command;
-import javacard.security.KeyPair;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import static cz.crcs.ectester.common.test.Result.ExpectedValue;
-
-/**
- * @author Jan Jancar johny@neuromancer.sk
- */
-public class CardInvalidCurvesSuite extends CardTestSuite {
-
- public CardInvalidCurvesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "invalid", "The invalid curve suite tests whether the card rejects points outside of the curve during ECDH.");
- }
-
- @Override
- protected void runTests() throws Exception {
- /* Set original curves (secg/nist/brainpool). Generate local.
- * Try ECDH with invalid public keys of increasing (or decreasing) order.
- */
- Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "invalid");
- Map<EC_Curve, List<EC_Key.Public>> curves = new HashMap<>();
- for (EC_Key.Public key : pubkeys.values()) {
- EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, key.getCurve());
- if (curve.getBits() != cfg.bits && !cfg.all) {
- continue;
- }
- if (curve.getField() == KeyPair.ALG_EC_FP && !cfg.primeField || curve.getField() == KeyPair.ALG_EC_F2M && !cfg.binaryField) {
- continue;
- }
- List<EC_Key.Public> keys = curves.getOrDefault(curve, new LinkedList<>());
- keys.add(key);
- curves.putIfAbsent(curve, keys);
- }
- for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curves.entrySet()) {
- EC_Curve curve = e.getKey();
- List<EC_Key.Public> keys = e.getValue();
-
- doTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS));
- doTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS));
- doTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.SUCCESS));
- List<Test> ecdhTests = new LinkedList<>();
- for (EC_Key.Public pub : keys) {
- Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
- ecdhTests.add(CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on invalid curve.", "Card incorrectly accepted point on invalid curve."));
- }
- doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId(), ecdhTests.toArray(new Test[0])));
- new Command.Cleanup(this.card).send();
- }
- }
-}
diff --git a/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java
new file mode 100644
index 0000000..59a427f
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java
@@ -0,0 +1,81 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+import cz.crcs.ectester.common.ec.EC_Key;
+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.data.EC_Store;
+import cz.crcs.ectester.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
+import cz.crcs.ectester.reader.command.Command;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import static cz.crcs.ectester.common.test.Result.ExpectedValue;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardInvalidSuite extends CardTestSuite {
+
+ public CardInvalidSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ super(writer, cfg, cardManager, "invalid", "The invalid curve suite tests whether the card rejects points outside of the curve during ECDH.");
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ /* Set original curves (secg/nist/brainpool). Generate local.
+ * Try ECDH with invalid public keys of increasing order.
+ */
+ Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "invalid");
+ List<Map.Entry<EC_Curve, List<EC_Key.Public>>> curveList = EC_Store.mapKeyToCurve(pubkeys.values());
+ for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList) {
+ EC_Curve curve = e.getKey();
+ List<EC_Key.Public> keys = e.getValue();
+
+ Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS);
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS);
+ Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.SUCCESS);
+
+ Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate);
+
+ List<Test> ecdhTests = new LinkedList<>();
+ for (EC_Key.Public pub : keys) {
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
+ ecdhTests.add(CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on invalid curve.", "Card incorrectly accepted point on invalid curve."));
+ }
+ Test ecdh = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH with invalid public points", ecdhTests.toArray(new Test[0]));
+
+ Random r = new Random();
+ byte[] raw = new byte[128];
+ byte[] sig = new byte[40];
+ r.nextBytes(raw);
+ r.nextBytes(sig);
+
+ List<Test> ecdsaTests = new LinkedList<>();
+ for (EC_Key.Public pub : keys) {
+ Command setCommand = new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten());
+ Test setTest = CommandTest.expect(setCommand, Result.ExpectedValue.ANY);
+ Command ecdsaCommand = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.Signature_ALG_ECDSA_SHA, raw, sig);
+ Test ecdsaTest = CommandTest.expect(ecdsaCommand, Result.ExpectedValue.FAILURE);
+ ecdsaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by " + pub.getId(), setTest, ecdsaTest));
+ }
+ Test ecdsa = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by invalid public points", ecdsaTests.toArray(new Test[0]));
+
+ Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test ECDH and ECDSA with points on invalid curves.", ecdh, ecdsa);
+ if (cfg.cleanup) {
+ Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.SUCCESS);
+ doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId(), prepare, tests, cleanup));
+ } else {
+ doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId(), prepare, tests));
+ }
+ }
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java
new file mode 100644
index 0000000..e568f67
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java
@@ -0,0 +1,60 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+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.data.EC_Store;
+import cz.crcs.ectester.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
+import cz.crcs.ectester.reader.command.Command;
+
+import java.util.Map;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardMiscSuite extends CardTestSuite {
+
+ public CardMiscSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ super(writer, cfg, cardManager, "miscellaneous", "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves, anomalous curves and some Barreto-Naehrig curves with small embedding degree and CM discriminant.");
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ Map<String, EC_Curve> anCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "anomalous");
+ Map<String, EC_Curve> ssCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "supersingular");
+ Map<String, EC_Curve> bnCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "Barreto-Naehrig");
+
+ testCurves(anCurves, "anomalous", Result.ExpectedValue.FAILURE);
+ testCurves(ssCurves, "supersingular", Result.ExpectedValue.FAILURE);
+ testCurves(bnCurves, "Barreto-Naehrig", Result.ExpectedValue.ANY);
+ }
+
+ private void testCurves(Map<String, EC_Curve> curves, String catName, Result.ExpectedValue expected) throws Exception {
+ for (EC_Curve curve : curves.values()) {
+ Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS));
+ if (!allocateFirst.ok()) {
+ doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocateFirst));
+ continue;
+ }
+
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS);
+ Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.ANY);
+ Test ka = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), expected);
+ Test sig = CommandTest.expect(new Command.ECDSA(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_FALSE, null), expected);
+ Test perform = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH and ECDSA", ka, sig);
+
+ if (cfg.cleanup) {
+ Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.SUCCESS);
+ doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + " " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform, cleanup));
+ } else {
+ doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + " " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform));
+ }
+ }
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CardTestSuite.java b/src/cz/crcs/ectester/reader/test/CardTestSuite.java
index 0eccd16..3578f9c 100644
--- a/src/cz/crcs/ectester/reader/test/CardTestSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardTestSuite.java
@@ -12,7 +12,7 @@ public abstract class CardTestSuite extends TestSuite {
ECTesterReader.Config cfg;
CardMngr card;
- CardTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager, String name, String description) {
+ CardTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager, String name, String... description) {
super(writer, name, description);
this.card = cardManager;
this.cfg = cfg;
diff --git a/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java b/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
index 73c6621..052e480 100644
--- a/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
@@ -4,14 +4,16 @@ import cz.crcs.ectester.applet.ECTesterApplet;
import cz.crcs.ectester.applet.EC_Consts;
import cz.crcs.ectester.common.ec.*;
import cz.crcs.ectester.common.output.TestWriter;
-import cz.crcs.ectester.common.test.*;
+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.test.TestCallback;
import cz.crcs.ectester.common.util.ByteUtil;
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 javacard.security.KeyPair;
import java.io.IOException;
import java.util.LinkedList;
@@ -38,12 +40,6 @@ public class CardTestVectorSuite extends CardTestSuite {
Map<String, EC_KAResult> results = EC_Store.getInstance().getObjects(EC_KAResult.class, "test");
for (EC_KAResult result : results.values()) {
EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, result.getCurve());
- if (curve.getBits() != cfg.bits && !cfg.all) {
- continue;
- }
- if (curve.getField() == KeyPair.ALG_EC_FP && !cfg.primeField || curve.getField() == KeyPair.ALG_EC_F2M && !cfg.binaryField) {
- continue;
- }
EC_Params onekey = EC_Store.getInstance().getObject(EC_Keypair.class, result.getOneKey());
if (onekey == null) {
onekey = EC_Store.getInstance().getObject(EC_Key.Private.class, result.getOneKey());
@@ -61,7 +57,7 @@ public class CardTestVectorSuite extends CardTestSuite {
testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS));
testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, onekey.flatten(EC_Consts.PARAMETER_S)), ExpectedValue.SUCCESS));
testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_W, otherkey.flatten(EC_Consts.PARAMETER_W)), ExpectedValue.SUCCESS));
- testVector.add(CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_TRUE, EC_Consts.CORRUPTION_NONE, result.getJavaCardKA()), new TestCallback<CommandTestable>() {
+ testVector.add(CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, result.getJavaCardKA()), new TestCallback<CommandTestable>() {
@Override
public Result apply(CommandTestable testable) {
Response.ECDH dh = (Response.ECDH) testable.getResponse();
@@ -76,8 +72,10 @@ public class CardTestVectorSuite extends CardTestSuite {
return new Result(Value.SUCCESS);
}
}));
- doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Test vector " + result.getId(), testVector.toArray(new Test[0])));
- new Command.Cleanup(this.card).send();
+ if (cfg.cleanup) {
+ testVector.add(CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.SUCCESS));
+ }
+ doTest(CompoundTest.greedyAll(ExpectedValue.SUCCESS, "Test vector " + result.getId(), testVector.toArray(new Test[0])));
}
}
}
diff --git a/src/cz/crcs/ectester/reader/test/CardTwistSuite.java b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java
new file mode 100644
index 0000000..1e1f5f3
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java
@@ -0,0 +1,75 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+import cz.crcs.ectester.common.ec.EC_Key;
+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.data.EC_Store;
+import cz.crcs.ectester.reader.CardMngr;
+import cz.crcs.ectester.reader.ECTesterReader;
+import cz.crcs.ectester.reader.command.Command;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardTwistSuite extends CardTestSuite {
+ public CardTwistSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ 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
+ protected void runTests() throws Exception {
+ Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "twist");
+ List<Map.Entry<EC_Curve, List<EC_Key.Public>>> curveList = EC_Store.mapKeyToCurve(pubkeys.values());
+ for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList) {
+ EC_Curve curve = e.getKey();
+ List<EC_Key.Public> keys = e.getValue();
+
+ Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS);
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS);
+ Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS);
+
+ Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate);
+
+ List<Test> ecdhTests = new LinkedList<>();
+ for (EC_Key.Public pub : keys) {
+ Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
+ ecdhTests.add(CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on twist.", "Card incorrectly accepted point on twist."));
+ }
+ Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with public points on twist", ecdhTests.toArray(new Test[0]));
+
+ Random r = new Random();
+ byte[] raw = new byte[128];
+ byte[] sig = new byte[40];
+ r.nextBytes(raw);
+ r.nextBytes(sig);
+
+ List<Test> ecdsaTests = new LinkedList<>();
+ for (EC_Key.Public pub : keys) {
+ Command setCommand = new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten());
+ Test setTest = CommandTest.expect(setCommand, Result.ExpectedValue.ANY);
+ Command ecdsaCommand = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.Signature_ALG_ECDSA_SHA, raw, sig);
+ Test ecdsaTest = CommandTest.expect(ecdsaCommand, Result.ExpectedValue.FAILURE);
+ ecdsaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by " + pub.getId(), setTest, ecdsaTest));
+ }
+ Test ecdsa = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Verify random ECDSA signature by public points on twist", ecdsaTests.toArray(new Test[0]));
+
+ Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, ecdh, ecdsa);
+ if (cfg.cleanup) {
+ Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.SUCCESS);
+ doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId(), prepare, tests, cleanup));
+ } else {
+ doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId(), prepare, tests));
+ }
+ }
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java b/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java
deleted file mode 100644
index c43b234..0000000
--- a/src/cz/crcs/ectester/reader/test/CardTwistTestSuite.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package cz.crcs.ectester.reader.test;
-
-import cz.crcs.ectester.applet.ECTesterApplet;
-import cz.crcs.ectester.applet.EC_Consts;
-import cz.crcs.ectester.common.ec.EC_Curve;
-import cz.crcs.ectester.common.ec.EC_Key;
-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.data.EC_Store;
-import cz.crcs.ectester.reader.CardMngr;
-import cz.crcs.ectester.reader.ECTesterReader;
-import cz.crcs.ectester.reader.command.Command;
-import javacard.security.KeyPair;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Jan Jancar johny@neuromancer.sk
- */
-public class CardTwistTestSuite extends CardTestSuite {
- public CardTwistTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- 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
- protected void runTests() throws Exception {
- Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "twist");
- Map<EC_Curve, List<EC_Key.Public>> curves = new HashMap<>();
- for (EC_Key.Public key : pubkeys.values()) {
- EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, key.getCurve());
- if (curve.getBits() != cfg.bits && !cfg.all) {
- continue;
- }
- if (curve.getField() == KeyPair.ALG_EC_FP && !cfg.primeField || curve.getField() == KeyPair.ALG_EC_F2M && !cfg.binaryField) {
- continue;
- }
- List<EC_Key.Public> keys = curves.getOrDefault(curve, new LinkedList<>());
- keys.add(key);
- curves.putIfAbsent(curve, keys);
- }
- for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curves.entrySet()) {
- EC_Curve curve = e.getKey();
- List<EC_Key.Public> keys = e.getValue();
-
- doTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS));
- doTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS));
- doTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS));
- List<Test> ecdhTests = new LinkedList<>();
- for (EC_Key.Public pub : keys) {
- Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, ECTesterApplet.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten());
- ecdhTests.add(CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on twist.", "Card incorrectly accepted point on twist."));
- }
- doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId(), ecdhTests.toArray(new Test[0])));
- new Command.Cleanup(this.card).send();
- }
- }
-}
diff --git a/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java b/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java
deleted file mode 100644
index cac8fab..0000000
--- a/src/cz/crcs/ectester/reader/test/CardWrongCurvesSuite.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package cz.crcs.ectester.reader.test;
-
-import cz.crcs.ectester.applet.ECTesterApplet;
-import cz.crcs.ectester.applet.EC_Consts;
-import cz.crcs.ectester.common.ec.EC_Curve;
-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.data.EC_Store;
-import cz.crcs.ectester.reader.CardMngr;
-import cz.crcs.ectester.reader.ECTesterReader;
-import cz.crcs.ectester.reader.command.Command;
-import javacard.security.KeyPair;
-
-import java.util.Map;
-
-/**
- * @author Jan Jancar johny@neuromancer.sk
- */
-public class CardWrongCurvesSuite extends CardTestSuite {
-
- public CardWrongCurvesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
- super(writer, cfg, cardManager, "wrong", "The wrong curve suite run whether the card rejects domain parameters which are not curves.");
- }
-
- @Override
- protected void runTests() throws Exception {
- /* Just do the default run on the wrong curves.
- * These should generally fail, the curves aren't curves.
- */
- Map<String, EC_Curve> curves = EC_Store.getInstance().getObjects(EC_Curve.class, "wrong");
- for (Map.Entry<String, EC_Curve> e : curves.entrySet()) {
- EC_Curve curve = e.getValue();
- if (curve.getBits() != cfg.bits && !cfg.all) {
- continue;
- }
- if (curve.getField() == KeyPair.ALG_EC_FP && !cfg.primeField || curve.getField() == KeyPair.ALG_EC_F2M && !cfg.binaryField) {
- continue;
- }
- Test key = doTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS));
- if (!key.ok()) {
- continue;
- }
- Test set = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS));
- Test generate = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.SUCCESS));
- doTest(CompoundTest.any(Result.ExpectedValue.FAILURE, "Set wrong curve and generate keypairs, should fail." ,set, generate));
-
- for (byte kaType : EC_Consts.KA_TYPES) {
- Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), Result.ExpectedValue.SUCCESS));
- if (allocate.ok()) {
- Test ka = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, kaType), Result.ExpectedValue.FAILURE));
- doTest(CompoundTest.any(Result.ExpectedValue.FAILURE, "Allocate and perform KA, should fail.", allocate, ka));
- }
- }
- }
- }
-}
diff --git a/src/cz/crcs/ectester/reader/test/CardWrongSuite.java b/src/cz/crcs/ectester/reader/test/CardWrongSuite.java
new file mode 100644
index 0000000..8bc7c90
--- /dev/null
+++ b/src/cz/crcs/ectester/reader/test/CardWrongSuite.java
@@ -0,0 +1,227 @@
+package cz.crcs.ectester.reader.test;
+
+import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.common.ec.EC_Curve;
+import cz.crcs.ectester.common.ec.EC_Params;
+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.ByteUtil;
+import cz.crcs.ectester.common.util.CardUtil;
+import cz.crcs.ectester.common.util.ECUtil;
+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 javacard.security.KeyPair;
+
+import java.math.BigInteger;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import static cz.crcs.ectester.common.test.Result.ExpectedValue;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CardWrongSuite extends CardTestSuite {
+
+ public CardWrongSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) {
+ super(writer, cfg, cardManager, "wrong", "The wrong curve suite tests whether the card rejects domain parameters which are not curves.");
+ }
+
+ @Override
+ protected void runTests() throws Exception {
+ /* Just do the default run on the wrong curves.
+ * These should generally fail, the curves aren't curves.
+ */
+ Map<String, EC_Curve> curves = EC_Store.getInstance().getObjects(EC_Curve.class, "wrong");
+ for (Map.Entry<String, EC_Curve> e : curves.entrySet()) {
+ EC_Curve curve = e.getValue();
+ List<Test> tests = new LinkedList<>();
+ Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS));
+ if (!key.ok()) {
+ doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()), key));
+ continue;
+ }
+ tests.add(key);
+ Test set = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.FAILURE));
+ Test generate = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.FAILURE));
+ Test setup = runTest(CompoundTest.any(ExpectedValue.SUCCESS, "Set wrong curve and generate keypairs.", set, generate));
+ tests.add(setup);
+
+ for (byte kaType : EC_Consts.KA_TYPES) {
+ Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), ExpectedValue.SUCCESS));
+ if (allocate.ok()) {
+ Test ka = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType), ExpectedValue.FAILURE));
+ Test kaTest = runTest(CompoundTest.all(ExpectedValue.SUCCESS, "Allocate and perform KA.", allocate, ka));
+ tests.add(kaTest);
+ }
+ }
+ doTest(CompoundTest.function((tsts) -> {
+ for (int i = 0; i < tsts.length; ++i) {
+ if (i != 1 && !tsts[i].ok()) {
+ return new Result(Result.Value.FAILURE, "Some tests did not have the expected result.");
+ }
+ }
+ return new Result(Result.Value.SUCCESS, "All tests had the expected result.");
+ }, "Wrong curve test of " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()), tests.toArray(new Test[0])));
+ }
+ /*
+ * Do some interesting tests with corrupting the custom curves.
+ * For prime field:
+ * - p = 0
+ * - p = 1
+ * - p is a square of a prime
+ * - 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, KeyPair.ALG_EC_FP);
+ Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP), ExpectedValue.SUCCESS));
+ if (!key.ok()) {
+ doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + keyLength + "b ALG_EC_FP.", key));
+ continue;
+ }
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_FP, null), ExpectedValue.SUCCESS);
+ Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set);
+
+ Test prime0 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_FP, EC_Consts.TRANSFORMATION_ZERO), "Set p = 0.", "ECDH with p = 0.");
+ Test prime1 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_FP, EC_Consts.TRANSFORMATION_ONE), "Set p = 1.", "ECDH with p = 1.");
+
+ short keyHalf = (short) (keyLength / 2);
+ BigInteger prime = new BigInteger(keyHalf, 50, r);
+ BigInteger primePow = prime.pow(2);
+ byte[] primePowBytes = ECUtil.toByteArray(primePow, keyLength);
+ EC_Params primePowData = new EC_Params(EC_Consts.PARAMETER_FP, new byte[][]{primePowBytes});
+ Test primePower = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, primePowData.getParams(), primePowData.flatten()), "Set p = square of a prime.", "ECDH with p = q^2.");
+
+ BigInteger q = new BigInteger(keyHalf, r);
+ BigInteger s = new BigInteger(keyHalf, r);
+ BigInteger compositeValue = q.multiply(s);
+ byte[] compositeBytes = ECUtil.toByteArray(compositeValue, keyLength);
+ EC_Params compositeData = new EC_Params(EC_Consts.PARAMETER_FP, new byte[][]{compositeBytes});
+ Test composite = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, compositeData.getParams(), compositeData.flatten()), "Set p = product of two primes.", "ECDH with p = q * s.");
+
+ Test wrongPrime = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted prime parameter.", prime0, prime1, primePower, composite);
+
+ Test resetSetup = CompoundTest.all(ExpectedValue.SUCCESS, "Reset keypair.", set.clone());
+
+ Test randomG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, (short) (EC_Consts.TRANSFORMATION_FULLRANDOM | EC_Consts.TRANSFORMATION_04_MASK)), "Set G = random non-point/point-like.", "ECDH with non-point G.");
+ Test fullRandomG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, EC_Consts.TRANSFORMATION_FULLRANDOM), "Set G = random data.", "ECDH with G = random data.");
+ Test zeroG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, EC_Consts.TRANSFORMATION_INFINITY), "Set G = inifnity.", "ECDH with G = infinity.");
+ Test wrongG = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted G parameter.", randomG, fullRandomG, zeroG);
+
+ byte[] originalR = new byte[keyLength];
+ EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_R, originalR, (short) 0);
+ BigInteger originalBigR = new BigInteger(1, originalR);
+
+ Test zeroR = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, EC_Consts.PARAMETER_R, EC_Consts.TRANSFORMATION_ZERO), "Set R = 0.", "ECDH with R = 0.");
+ Test oneR = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, EC_Consts.PARAMETER_R, EC_Consts.TRANSFORMATION_ONE), "Set R = 1.", "ECDH with R = 1.");
+
+ BigInteger prevPrimeR;
+ do {
+ prevPrimeR = BigInteger.probablePrime(originalBigR.bitLength() - 1, r);
+ } while (prevPrimeR.compareTo(originalBigR) >= 0);
+ byte[] prevRBytes = ECUtil.toByteArray(prevPrimeR, keyLength);
+ EC_Params prevRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{prevRBytes});
+ Test prevprimeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, prevRData.getParams(), prevRData.flatten()), "Set R = some prime (but [r]G != infinity) smaller than original R.", "ECDH with wrong R, prevprime.");
+
+ BigInteger nextPrimeR = originalBigR.nextProbablePrime();
+ byte[] nextRBytes = ECUtil.toByteArray(nextPrimeR, keyLength);
+ EC_Params nextRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{nextRBytes});
+ Test nextprimeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, nextRData.getParams(), nextRData.flatten()), "Set R = some prime (but [r]G != infinity) larger than original R.", "ECDH with wrong R, nextprime.");
+
+ byte[] nonprimeRBytes = nextRBytes.clone();
+ nonprimeRBytes[0] ^= 1;
+ EC_Params nonprimeWrongRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{nonprimeRBytes});
+ Test nonprimeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, nonprimeWrongRData.getParams(), nonprimeWrongRData.flatten()), "Set R = some composite (but [r]G != infinity).", "ECDH with wrong R, composite.");
+
+ Test wrongR = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted R parameter.", zeroR, oneR, prevprimeWrongR, nextprimeWrongR, nonprimeWrongR);
+
+ byte[] kRaw = new byte[]{(byte) 0xff};
+ EC_Params kData = new EC_Params(EC_Consts.PARAMETER_K, new byte[][]{kRaw});
+ Test bigK = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, kData.getParams(), kData.flatten()), "", "");
+
+ byte[] kZero = new byte[]{(byte) 0};
+ EC_Params kZeroData = new EC_Params(EC_Consts.PARAMETER_K, new byte[][]{kZero});
+ Test zeroK = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, kZeroData.getParams(), kZeroData.flatten()), "", "");
+
+ Test wrongK = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted K parameter.", bigK, zeroK);
+
+ doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(KeyPair.ALG_EC_FP), setup, wrongPrime, resetSetup, wrongG, resetSetup.clone(), wrongR, resetSetup.clone(), wrongK, resetSetup.clone()));
+ }
+
+ /*
+ * For binary field:
+ * - e1, e2 or e3 is larger than m.
+ * - e1 = e2 = e3 = 0
+ */
+ for (short keyLength : EC_Consts.F2M_SIZES) {
+ byte curve = EC_Consts.getCurve(keyLength, KeyPair.ALG_EC_F2M);
+ Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M), ExpectedValue.SUCCESS));
+ if (!key.ok()) {
+ doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + keyLength + "b ALG_EC_F2M.", key));
+ continue;
+ }
+ Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_F2M, null), ExpectedValue.SUCCESS);
+ Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set);
+
+ Test coeff0 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_F2M, EC_Consts.TRANSFORMATION_ZERO), "Set e1 = e2 = e3 = 0.", "ECDH with wrong field polynomial: x^" + keyLength);
+
+ short e1 = (short) (2 * keyLength);
+ short e2 = (short) (3 * keyLength);
+ short e3 = (short) (4 * keyLength);
+ byte[][] coeffBytes = new byte[][]{
+ ByteUtil.shortToBytes(keyLength),
+ ByteUtil.shortToBytes(e1),
+ ByteUtil.shortToBytes(e2),
+ ByteUtil.shortToBytes(e3)};
+ EC_Params coeffParams = new EC_Params(EC_Consts.PARAMETER_F2M, coeffBytes);
+ Test coeffLarger = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, coeffParams.getParams(), coeffParams.flatten()), "Set e1=" + e1 + ", e2=" + e2 + ", e3=" + e3, "ECDH with wrong field poly, powers larger than " + keyLength);
+
+ Test wrong = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted field polynomial parameter.", coeff0, coeffLarger);
+ doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(KeyPair.ALG_EC_F2M), setup, wrong));
+ }
+
+ /*
+ * TODO: tests for both Fp and F2m:
+ * - generator not on curve,
+ * - generator not on proper subgroup of curve(as specified by order/cofactor),
+ * - wrong order,
+ * - wrong cofactor.
+ */
+ }
+
+ private Test ecdhTest(Command setupCmd, String prepareDesc, String fullDesc) {
+ Test setup = CommandTest.expect(setupCmd, ExpectedValue.FAILURE);
+ Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.FAILURE);
+ Test preparePhase = CompoundTest.any(ExpectedValue.SUCCESS, prepareDesc, setup, generate);
+ Test allocateECDH = CommandTest.expect(new Command.AllocateKeyAgreement(this.card, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ExpectedValue.SUCCESS);
+ Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ExpectedValue.FAILURE);
+
+
+ return CompoundTest.function((tests) -> {
+ if (preparePhase.ok() | !allocateECDH.ok() | ecdh.ok()) {
+ return new Result(Result.Value.SUCCESS, "All tests had the expected result.");
+ } else {
+ return new Result(Result.Value.FAILURE, "Some tests did not have the expected result.");
+ }
+ }, (tests) -> {
+ preparePhase.run();
+ if (preparePhase.ok()) {
+ return;
+ }
+ allocateECDH.run();
+ if (!allocateECDH.ok()) {
+ return;
+ }
+ ecdh.run();
+ }, fullDesc, preparePhase, allocateECDH, ecdh);
+ }
+}
diff --git a/src/cz/crcs/ectester/reader/test/CommandTest.java b/src/cz/crcs/ectester/reader/test/CommandTest.java
index a08d820..d57dc17 100644
--- a/src/cz/crcs/ectester/reader/test/CommandTest.java
+++ b/src/cz/crcs/ectester/reader/test/CommandTest.java
@@ -3,13 +3,14 @@ package cz.crcs.ectester.reader.test;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.SimpleTest;
import cz.crcs.ectester.common.test.TestCallback;
-import cz.crcs.ectester.common.test.TestException;
import cz.crcs.ectester.reader.command.Command;
import cz.crcs.ectester.reader.response.Response;
/**
* A simple test that runs one Command to get and evaluate one Response
* to get a Result and compare it with the expected one.
+ *
+ * @author Jan Jancar johny@neuromancer.sk
*/
public class CommandTest extends SimpleTest<CommandTestable> {
private CommandTest(CommandTestable command, TestCallback<CommandTestable> callback) {
@@ -28,8 +29,7 @@ public class CommandTest extends SimpleTest<CommandTestable> {
return new CommandTest(command, new TestCallback<CommandTestable>() {
@Override
public Result apply(CommandTestable commandTestable) {
- Response resp = commandTestable.getResponse();
- Result.Value resultValue = Result.Value.fromExpected(expected, resp.successful(), resp.error());
+ Result.Value resultValue = Result.Value.fromExpected(expected, commandTestable.ok(), commandTestable.error());
return new Result(resultValue, resultValue.ok() ? ok : nok);
}
});
@@ -56,21 +56,11 @@ public class CommandTest extends SimpleTest<CommandTestable> {
}
@Override
- public void run() throws TestException {
- if (hasRun)
- return;
-
- testable.run();
- result = callback.apply(testable);
- hasRun = true;
- }
-
- @Override
public String getDescription() {
if (hasRun) {
return testable.getResponse().getDescription();
} else {
- return testable.getCommand().toString();
+ return testable.getCommand().getDescription();
}
}
}
diff --git a/src/cz/crcs/ectester/reader/test/CommandTestable.java b/src/cz/crcs/ectester/reader/test/CommandTestable.java
index 3bb55bf..f670534 100644
--- a/src/cz/crcs/ectester/reader/test/CommandTestable.java
+++ b/src/cz/crcs/ectester/reader/test/CommandTestable.java
@@ -27,7 +27,7 @@ public class CommandTestable extends BaseTestable {
}
@Override
- public void run() throws TestException {
+ public void run() {
try {
response = command.send();
} catch (CardException e) {
diff --git a/src/cz/crcs/ectester/reader/test/PerformanceTest.java b/src/cz/crcs/ectester/reader/test/PerformanceTest.java
index 4a27bad..9abaadc 100644
--- a/src/cz/crcs/ectester/reader/test/PerformanceTest.java
+++ b/src/cz/crcs/ectester/reader/test/PerformanceTest.java
@@ -5,6 +5,7 @@ import cz.crcs.ectester.common.test.SimpleTest;
import cz.crcs.ectester.common.test.TestCallback;
import cz.crcs.ectester.common.test.TestException;
import cz.crcs.ectester.reader.command.Command;
+import cz.crcs.ectester.reader.response.Response;
import java.util.Arrays;
@@ -13,12 +14,14 @@ import java.util.Arrays;
*/
public class PerformanceTest extends SimpleTest<CommandTestable> {
private long[] times;
+ private Response[] responses;
private long mean;
private long median;
private long mode;
private int count;
+ private String desc;
- private PerformanceTest(CommandTestable testable, int count) {
+ private PerformanceTest(CommandTestable testable, int count, String desc) {
super(testable, new TestCallback<CommandTestable>() {
@Override
public Result apply(CommandTestable testable) {
@@ -26,26 +29,31 @@ public class PerformanceTest extends SimpleTest<CommandTestable> {
}
});
this.count = count;
+ this.desc = desc;
}
public static PerformanceTest repeat(Command cmd, int count) {
- return new PerformanceTest(new CommandTestable(cmd), count);
+ return new PerformanceTest(new CommandTestable(cmd), count, null);
+ }
+
+ public static PerformanceTest repeat(String desc, Command cmd, int count) {
+ return new PerformanceTest(new CommandTestable(cmd), count, desc);
}
@Override
public String getDescription() {
- return String.format("Mean = %d ns, Median = %d ns, Mode = %d ns", mean, median, mode);
+ String rest = String.format("Mean = %d ns, Median = %d ns, Mode = %d ns", mean, median, mode);
+ return (desc == null ? rest : desc + " (" + rest + ")");
}
@Override
- public void run() throws TestException {
- if (hasRun)
- return;
-
+ protected void runSelf() {
times = new long[count];
+ responses = new Response[count];
for (int i = 0; i < count; ++i) {
testable.run();
- times[i] = testable.getResponse().getDuration();
+ responses[i] = testable.getResponse();
+ times[i] = responses[i].getDuration();
testable.reset();
}
@@ -73,7 +81,6 @@ public class PerformanceTest extends SimpleTest<CommandTestable> {
mode = current_value;
}
}
- hasRun = true;
result = callback.apply(testable);
}
@@ -85,6 +92,10 @@ public class PerformanceTest extends SimpleTest<CommandTestable> {
return testable.getCommand();
}
+ public Response[] getResponses() {
+ return responses;
+ }
+
public long[] getTimes() {
return times;
}
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index f5361c3..31d291c 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -1,3 +1,25 @@
+/*
+ * ECTester, tool for testing Elliptic curve cryptography implementations.
+ * Copyright (c) 2016-2018 Petr Svenda <petr@svenda.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
package cz.crcs.ectester.standalone;
import cz.crcs.ectester.common.cli.*;
@@ -14,14 +36,15 @@ import cz.crcs.ectester.standalone.libs.*;
import cz.crcs.ectester.standalone.output.TextTestWriter;
import cz.crcs.ectester.standalone.output.XMLTestWriter;
import cz.crcs.ectester.standalone.output.YAMLTestWriter;
-import cz.crcs.ectester.standalone.test.StandaloneDefaultSuite;
-import cz.crcs.ectester.standalone.test.StandaloneTestSuite;
+import cz.crcs.ectester.standalone.test.suites.StandaloneDefaultSuite;
+import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
@@ -31,6 +54,7 @@ import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.util.*;
import java.util.stream.Collectors;
@@ -39,18 +63,18 @@ import java.util.stream.Collectors;
* Standalone part of ECTester, a tool for testing Elliptic curve implementations in software libraries.
*
* @author Jan Jancar johny@neuromancer.sk
- * @version v0.1.0
+ * @version v0.2.0
*/
public class ECTesterStandalone {
- private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib()};
+ private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new MscngLib()};
private Config cfg;
private Options opts = new Options();
private TreeParser optParser;
private TreeCommandLine cli;
- private static final String VERSION = "v0.1.0";
+ public static final String VERSION = "v0.2.0";
private static final String DESCRIPTION = "ECTesterStandalone " + VERSION + ", an Elliptic Curve Cryptography support tester/utility.";
- private static final String LICENSE = "MIT Licensed\nCopyright (c) 2016-2017 Petr Svenda <petr@svenda.com>";
+ private static final String LICENSE = "MIT Licensed\nCopyright (c) 2016-2018 Petr Svenda <petr@svenda.com>";
private static final String CLI_HEADER = "\n" + DESCRIPTION + "\n\n";
private static final String CLI_FOOTER = "\n" + LICENSE;
@@ -79,6 +103,8 @@ public class ECTesterStandalone {
listLibraries();
} else if (cli.isNext("list-data")) {
CLITools.listNamed(EC_Store.getInstance(), cli.getNext().getArg(0));
+ } else if (cli.isNext("list-suites")) {
+ listSuites();
} else if (cli.isNext("ecdh")) {
ecdh();
} else if (cli.isNext("ecdsa")) {
@@ -98,7 +124,7 @@ public class ECTesterStandalone {
} catch (NoSuchAlgorithmException nsaex) {
System.err.println("Algorithm not supported by the selected library: " + nsaex.getMessage());
nsaex.printStackTrace();
- } catch (InvalidKeyException | SignatureException | TestException e) {
+ } catch (InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
@@ -106,68 +132,80 @@ public class ECTesterStandalone {
private TreeCommandLine parseArgs(String[] args) throws ParseException {
Map<String, ParserOptions> actions = new TreeMap<>();
- Option namedCurve = Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: <cat/id>").hasArg().argName("cat/id").build();
+ Option namedCurve = Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: <cat/id>").hasArg().argName("cat/id").optionalArg(false).build();
+ Option curveName = Option.builder("cn").longOpt("curve-name").desc("Use a named curve, search from curves supported by the library: <name>").hasArg().argName("name").optionalArg(false).build();
Option bits = Option.builder("b").longOpt("bits").hasArg().argName("n").optionalArg(false).desc("What size of curve to use.").build();
Options testOpts = new Options();
testOpts.addOption(bits);
testOpts.addOption(namedCurve);
+ testOpts.addOption(curveName);
testOpts.addOption(Option.builder("gt").longOpt("kpg-type").desc("Set the KeyPairGenerator object [type].").hasArg().argName("type").optionalArg(false).build());
testOpts.addOption(Option.builder("kt").longOpt("ka-type").desc("Set the KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build());
testOpts.addOption(Option.builder("st").longOpt("sig-type").desc("Set the Signature object [type].").hasArg().argName("type").optionalArg(false).build());
testOpts.addOption(Option.builder("f").longOpt("format").desc("Set the output format, one of text,yaml,xml.").hasArg().argName("format").optionalArg(false).build());
+ testOpts.addOption(Option.builder().longOpt("key-type").desc("Set the key [algorithm] for which the key should be derived in KeyAgreements with KDF. Default is \"AES\".").hasArg().argName("algorithm").optionalArg(false).build());
List<Argument> testArgs = new LinkedList<>();
- testArgs.add(new Argument("test_suite", "The test suite to run.", true));
- ParserOptions test = new ParserOptions(new DefaultParser(), testOpts, testArgs);
+ testArgs.add(new Argument("test-suite", "The test suite to run.", true));
+ ParserOptions test = new ParserOptions(new TreeParser(Collections.emptyMap(), true, testArgs), testOpts, "Test a library.");
actions.put("test", test);
Options ecdhOpts = new Options();
ecdhOpts.addOption(bits);
ecdhOpts.addOption(namedCurve);
+ ecdhOpts.addOption(curveName);
ecdhOpts.addOption(Option.builder("t").longOpt("type").desc("Set KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build());
+ ecdhOpts.addOption(Option.builder().longOpt("key-type").desc("Set the key [algorithm] for which the key should be derived in KeyAgreements with KDF. Default is \"AES\".").hasArg().argName("algorithm").optionalArg(false).build());
ecdhOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDH [amount] times.").build());
- ParserOptions ecdh = new ParserOptions(new DefaultParser(), ecdhOpts);
+ ParserOptions ecdh = new ParserOptions(new DefaultParser(), ecdhOpts, "Perform EC based KeyAgreement.");
actions.put("ecdh", ecdh);
Options ecdsaOpts = new Options();
ecdsaOpts.addOption(bits);
ecdsaOpts.addOption(namedCurve);
+ ecdsaOpts.addOption(curveName);
ecdsaOpts.addOption(Option.builder("t").longOpt("type").desc("Set Signature object [type].").hasArg().argName("type").optionalArg(false).build());
ecdsaOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDSA [amount] times.").build());
ecdsaOpts.addOption(Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build());
- ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts);
+ ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts, "Perform EC based Signature.");
actions.put("ecdsa", ecdsa);
Options generateOpts = new Options();
generateOpts.addOption(bits);
generateOpts.addOption(namedCurve);
+ generateOpts.addOption(curveName);
generateOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Generate [amount] of EC keys.").build());
generateOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPairGenerator object [type].").build());
- ParserOptions generate = new ParserOptions(new DefaultParser(), generateOpts);
+ ParserOptions generate = new ParserOptions(new DefaultParser(), generateOpts, "Generate EC keypairs.");
actions.put("generate", generate);
Options exportOpts = new Options();
- exportOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPair object [type].").build());
exportOpts.addOption(bits);
- ParserOptions export = new ParserOptions(new DefaultParser(), exportOpts);
+ exportOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPair object [type].").build());
+ ParserOptions export = new ParserOptions(new DefaultParser(), exportOpts, "Export default curve parameters.");
actions.put("export", export);
Options listDataOpts = new Options();
List<Argument> listDataArgs = new LinkedList<>();
listDataArgs.add(new Argument("what", "what to list.", false));
- ParserOptions listData = new ParserOptions(new TreeParser(Collections.emptyMap(), false, listDataArgs), listDataOpts);
+ ParserOptions listData = new ParserOptions(new TreeParser(Collections.emptyMap(), false, listDataArgs), listDataOpts, "List/show contained EC domain parameters/keys.");
actions.put("list-data", listData);
Options listLibsOpts = new Options();
- ParserOptions listLibs = new ParserOptions(new DefaultParser(), listLibsOpts);
+ ParserOptions listLibs = new ParserOptions(new DefaultParser(), listLibsOpts, "List supported libraries.");
actions.put("list-libs", listLibs);
+ Options listSuitesOpts = new Options();
+ ParserOptions listSuites = new ParserOptions(new DefaultParser(), listSuitesOpts, "List supported test suites.");
+ actions.put("list-suites", listSuites);
+
List<Argument> baseArgs = new LinkedList<>();
baseArgs.add(new Argument("lib", "What library to use.", false));
optParser = new TreeParser(actions, false, baseArgs);
opts.addOption(Option.builder("V").longOpt("version").desc("Print version info.").build());
opts.addOption(Option.builder("h").longOpt("help").desc("Print help.").build());
+ opts.addOption(Option.builder("C").longOpt("color").desc("Print stuff with color, requires ANSI terminal.").build());
return optParser.parse(opts, args);
}
@@ -176,24 +214,24 @@ public class ECTesterStandalone {
*
*/
private void listLibraries() {
- for (ECLibrary lib : libs) {
+ for (ProviderECLibrary lib : libs) {
if (lib.isInitialized() && (cfg.selected == null || lib == cfg.selected)) {
- System.out.println("\t- " + lib.name());
+ System.out.println("\t- " + Colors.bold(lib.name()));
Set<KeyPairGeneratorIdent> kpgs = lib.getKPGs();
if (!kpgs.isEmpty()) {
- System.out.println("\t\t- KeyPairGenerators: " + String.join(",", kpgs.stream().map(KeyPairGeneratorIdent::getName).collect(Collectors.toList())));
+ System.out.println(Colors.bold("\t\t- KeyPairGenerators: ") + String.join(", ", kpgs.stream().map(KeyPairGeneratorIdent::getName).collect(Collectors.toList())));
}
Set<KeyAgreementIdent> eckas = lib.getKAs();
if (!eckas.isEmpty()) {
- System.out.println("\t\t- KeyAgreements: " + String.join(",", eckas.stream().map(KeyAgreementIdent::getName).collect(Collectors.toList())));
+ System.out.println(Colors.bold("\t\t- KeyAgreements: ") + String.join(", ", eckas.stream().map(KeyAgreementIdent::getName).collect(Collectors.toList())));
}
Set<SignatureIdent> sigs = lib.getSigs();
if (!sigs.isEmpty()) {
- System.out.println("\t\t- Signatures: " + String.join(",", sigs.stream().map(SignatureIdent::getName).collect(Collectors.toList())));
+ System.out.println(Colors.bold("\t\t- Signatures: ") + String.join(", ", sigs.stream().map(SignatureIdent::getName).collect(Collectors.toList())));
}
Set<String> curves = lib.getCurves();
if (!curves.isEmpty()) {
- System.out.println("\t\t- Curves: " + String.join(",", curves));
+ System.out.println(Colors.bold("\t\t- Curves: ") + String.join(", ", curves));
}
System.out.println();
}
@@ -203,10 +241,24 @@ public class ECTesterStandalone {
/**
*
*/
+ private void listSuites() {
+ StandaloneTestSuite[] suites = new StandaloneTestSuite[]{new StandaloneDefaultSuite(null, null, null)};
+ for (StandaloneTestSuite suite : suites) {
+ System.out.println(" - " + suite.getName());
+ for (String line : suite.getDescription()) {
+ System.out.println("\t" + line);
+ }
+ }
+ }
+
+ /**
+ *
+ */
private void ecdh() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException {
ProviderECLibrary lib = cfg.selected;
String algo = cli.getOptionValue("ecdh.type", "ECDH");
+ String keyAlgo = cli.getOptionValue("ecdh.key-type", "AES");
KeyAgreementIdent kaIdent = lib.getKAs().stream()
.filter((ident) -> ident.contains(algo))
.findFirst()
@@ -223,7 +275,6 @@ public class ECTesterStandalone {
.findFirst()
.orElse(null)));
-
if (kaIdent == null || kpIdent == null) {
throw new NoSuchAlgorithmException(algo);
} else {
@@ -242,7 +293,11 @@ public class ECTesterStandalone {
}
spec = curve.toSpec();
kpg.initialize(spec);
- }//TODO: allow ECGenNamedSpec
+ } else if (cli.hasOption("ecdh.curve-name")) {
+ String curveName = cli.getOptionValue("ecdh.curve-name");
+ spec = new ECGenParameterSpec(curveName);
+ kpg.initialize(spec);
+ }
System.out.println("index;nanotime;pubW;privS;secret");
@@ -262,7 +317,16 @@ public class ECTesterStandalone {
}
ka.doPhase(pubkey, true);
elapsed += System.nanoTime();
- byte[] result = ka.generateSecret();
+ SecretKey derived;
+ byte[] result;
+ elapsed -= System.nanoTime();
+ if (kaIdent.requiresKeyAlgo()) {
+ derived = ka.generateSecret(keyAlgo);
+ result = derived.getEncoded();
+ } else {
+ result = ka.generateSecret();
+ }
+ elapsed += System.nanoTime();
ka = kaIdent.getInstance(lib.getProvider());
String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
@@ -327,6 +391,9 @@ public class ECTesterStandalone {
return;
}
kpg.initialize(curve.toSpec());
+ } else if (cli.hasOption("ecdsa.curve-name")) {
+ String curveName = cli.getOptionValue("ecdsa.curve-name");
+ kpg.initialize(new ECGenParameterSpec(curveName));
}
System.out.println("index;data;signtime;verifytime;pubW;privS;signature;verified");
@@ -389,6 +456,9 @@ public class ECTesterStandalone {
return;
}
kpg.initialize(curve.toSpec());
+ } else if (cli.hasOption("generate.curve-name")) {
+ String curveName = cli.getOptionValue("generate.curve-name");
+ kpg.initialize(new ECGenParameterSpec(curveName));
}
System.out.println("index;nanotime;pubW;privS");
@@ -410,7 +480,7 @@ public class ECTesterStandalone {
/**
*
*/
- private void test() throws NoSuchAlgorithmException, TestException, ParserConfigurationException {
+ private void test() throws TestException, ParserConfigurationException {
TestWriter writer;
switch (cli.getOptionValue("test.format", "text").toLowerCase()) {
case "yaml":
@@ -434,7 +504,7 @@ public class ECTesterStandalone {
*
*/
private void export() throws NoSuchAlgorithmException, IOException {
- ProviderECLibrary lib = (ProviderECLibrary) cfg.selected;
+ ProviderECLibrary lib = cfg.selected;
KeyPairGeneratorIdent ident = null;
String algo = cli.getOptionValue("export.type", "EC");
for (KeyPairGeneratorIdent kpIdent : lib.getKPGs()) {
@@ -472,12 +542,16 @@ public class ECTesterStandalone {
public static class Config {
private ProviderECLibrary[] libs;
public ProviderECLibrary selected = null;
+ public boolean color = false;
public Config(ProviderECLibrary[] libs) {
this.libs = libs;
}
boolean readOptions(TreeCommandLine cli) {
+ color = cli.hasOption("color");
+ Colors.enabled = color;
+
if (cli.isNext("generate") || cli.isNext("export") || cli.isNext("ecdh") || cli.isNext("ecdsa") || cli.isNext("test")) {
if (!cli.hasArg(-1)) {
System.err.println("Missing library name argument.");
@@ -485,28 +559,33 @@ public class ECTesterStandalone {
}
String next = cli.getNextName();
- if (cli.hasOption(next + ".bits") && cli.hasOption(next + ".named-curve")) {
- System.err.println("You can only specify bitsize or a named curve, nor both.");
+ boolean hasBits = cli.hasOption(next + ".bits");
+ boolean hasNamedCurve = cli.hasOption(next + ".named-curve");
+ boolean hasCurveName = cli.hasOption(next + ".curve-name");
+ if (hasBits ^ hasNamedCurve ? hasCurveName : hasBits) {
+ System.err.println("You can only specify bitsize or a named curve/curve name, nor both.");
return false;
}
}
- String libraryName = cli.getArg(-1);
- if (libraryName != null) {
- List<ProviderECLibrary> matchedLibs = new LinkedList<>();
- for (ProviderECLibrary lib : libs) {
- if (lib.name().toLowerCase().contains(libraryName.toLowerCase())) {
- matchedLibs.add(lib);
+ if (!cli.isNext("list-data") && !cli.isNext("list-suites")) {
+ String libraryName = cli.getArg(-1);
+ if (libraryName != null) {
+ List<ProviderECLibrary> matchedLibs = new LinkedList<>();
+ for (ProviderECLibrary lib : libs) {
+ if (lib.isInitialized() && lib.name().toLowerCase().contains(libraryName.toLowerCase())) {
+ matchedLibs.add(lib);
+ }
+ }
+ if (matchedLibs.size() == 0) {
+ System.err.println("No library " + libraryName + " found.");
+ return false;
+ } else if (matchedLibs.size() > 1) {
+ System.err.println("Multiple matching libraries found: " + String.join(",", matchedLibs.stream().map(ECLibrary::name).collect(Collectors.toList())));
+ return false;
+ } else {
+ selected = matchedLibs.get(0);
}
- }
- if (matchedLibs.size() == 0) {
- System.err.println("No library " + libraryName + " found.");
- return false;
- } else if (matchedLibs.size() > 1) {
- System.err.println("Multiple matching libraries found: " + String.join(",", matchedLibs.stream().map(ECLibrary::name).collect(Collectors.toList())));
- return false;
- } else {
- selected = matchedLibs.get(0);
}
}
diff --git a/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java b/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java
index 0e4d311..94e8c84 100644
--- a/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java
+++ b/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java
@@ -10,6 +10,8 @@ import java.util.List;
* @author Jan Jancar johny@neuromancer.sk
*/
public class KeyAgreementIdent extends Ident {
+ private boolean requiresKeyAlgo;
+
private static final List<KeyAgreementIdent> ALL = new LinkedList<>();
static {
@@ -18,23 +20,36 @@ public class KeyAgreementIdent extends Ident {
ALL.add(new KeyAgreementIdent("ECDH"));
ALL.add(new KeyAgreementIdent("ECDHC", "ECCDH"));
// ECDH and ECDHC with SHA as KDF, OIDs from RFC 3278
- ALL.add(new KeyAgreementIdent("ECDHwithSHA1KDF", "1.3.133.16.840.63.0.2"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA1KDF", "1.3.133.16.840.63.0.3"));
- ALL.add(new KeyAgreementIdent("ECDHwithSHA224KDF", "1.3.132.1.11.0"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA224KDF", "1.3.132.1.14.0"));
- ALL.add(new KeyAgreementIdent("ECDHwithSHA256KDF", "1.3.132.1.11.1"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA256KDF", "1.3.132.1.14.1"));
- ALL.add(new KeyAgreementIdent("ECDHwithSHA384KDF", "1.3.132.1.11.2"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA384KDF", "1.3.132.1.14.2"));
- ALL.add(new KeyAgreementIdent("ECDHwithSHA512KDF", "1.3.132.1.11.3"));
- ALL.add(new KeyAgreementIdent("ECCDHwithSHA512KDF", "1.3.132.1.14.3"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA1KDF", true, "1.3.133.16.840.63.0.2"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA1KDF", true, "1.3.133.16.840.63.0.3"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA224KDF",true, "1.3.132.1.11.0"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA224KDF", true, "1.3.132.1.14.0"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA256KDF", true, "1.3.132.1.11.1"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA256KDF", true, "1.3.132.1.14.1"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA384KDF", true, "1.3.132.1.11.2"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA384KDF", true, "1.3.132.1.14.2"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA512KDF", true, "1.3.132.1.11.3"));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA512KDF", true, "1.3.132.1.14.3"));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA1CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA1CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA256CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA256CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA384CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA384CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECDHwithSHA512CKDF", true));
+ ALL.add(new KeyAgreementIdent("ECCDHwithSHA512CKDF", true));
// ECMQV - Disable for now as it needs diferent params(too different from DH)
//ALL.add(new KeyAgreementIdent("ECMQV"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA1CKDF", "1.3.133.16.840.63.0.16"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA224CKDF", "1.3.132.1.15.0"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA256CKDF", "1.3.132.1.15.1"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA384CKDF", "1.3.132.1.15.2"));
- //ALL.add(new KeyAgreementIdent("ECMQVwithSHA512CKDF", "1.3.132.1.15.3"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA1KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA224KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA256KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA354KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA512KDF", true));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA1CKDF", true, "1.3.133.16.840.63.0.16"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA224CKDF", true, "1.3.132.1.15.0"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA256CKDF", true, "1.3.132.1.15.1"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA384CKDF", true, "1.3.132.1.15.2"));
+ //ALL.add(new KeyAgreementIdent("ECMQVwithSHA512CKDF", true, "1.3.132.1.15.3"));
// ECVKO - Disable for now as it needs diferent params(too different from DH)
//ALL.add(new KeyAgreementIdent("ECVKO", "ECGOST3410", "1.2.643.2.2.19", "GOST-3410-2001", "1.2.643.2.2.96"));
//ALL.add(new KeyAgreementIdent("ECVKO256", "ECGOST3410-2012-256", "1.2.643.7.1.1.6.1", "1.2.643.7.1.1.1.1"));
@@ -54,6 +69,15 @@ public class KeyAgreementIdent extends Ident {
super(name, aliases);
}
+ private KeyAgreementIdent(String name, boolean requiresKeyAlgo, String... aliases) {
+ this(name, aliases);
+ this.requiresKeyAlgo = requiresKeyAlgo;
+ }
+
+ public boolean requiresKeyAlgo() {
+ return requiresKeyAlgo;
+ }
+
public KeyAgreement getInstance(Provider provider) throws NoSuchAlgorithmException {
KeyAgreement instance = getInstance((algorithm, provider1) -> {
try {
diff --git a/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java b/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java
index 8e67967..332b78e 100644
--- a/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java
+++ b/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java
@@ -15,8 +15,8 @@ public class KeyPairGeneratorIdent extends Ident {
ALL.add(new KeyPairGeneratorIdent("ECDSA"));
ALL.add(new KeyPairGeneratorIdent("ECDHC"));
ALL.add(new KeyPairGeneratorIdent("ECMQV"));
- ALL.add(new KeyPairGeneratorIdent("ECGOST3410"));
- ALL.add(new KeyPairGeneratorIdent("ECGOST3410-2012"));
+ //ALL.add(new KeyPairGeneratorIdent("ECGOST3410"));
+ //ALL.add(new KeyPairGeneratorIdent("ECGOST3410-2012"));
// ECKCDSA? Botan provides.
ALL.add(new KeyPairGeneratorIdent("ECKCDSA"));
// ECGDSA? Botan provides.
diff --git a/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java b/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java
new file mode 100644
index 0000000..5112d7d
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java
@@ -0,0 +1,20 @@
+package cz.crcs.ectester.standalone.libs;
+
+import java.security.Provider;
+import java.util.Set;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class CryptoppLib extends NativeECLibrary {
+
+ public CryptoppLib() {
+ super("cryptopp_provider", "cryptopp");
+ }
+
+ @Override
+ native Provider createProvider();
+
+ @Override
+ public native Set<String> getCurves();
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/MscngLib.java b/src/cz/crcs/ectester/standalone/libs/MscngLib.java
new file mode 100644
index 0000000..527a65b
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/MscngLib.java
@@ -0,0 +1,20 @@
+package cz.crcs.ectester.standalone.libs;
+
+import java.security.Provider;
+import java.util.Set;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class MscngLib extends NativeECLibrary {
+
+ public MscngLib() {
+ super("mscng_provider", "bcrypt");
+ }
+
+ @Override
+ native Provider createProvider();
+
+ @Override
+ public native Set<String> getCurves();
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java b/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
index 0a420a1..03a088b 100644
--- a/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
+++ b/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
@@ -110,7 +110,8 @@ public abstract class NativeECLibrary extends ProviderECLibrary {
provider = createProvider();
return super.initialize();
- } catch (IOException | UnsatisfiedLinkError ignored) {
+ } catch (IOException | UnsatisfiedLinkError ex) {
+ System.err.println(ex.getMessage());
}
return false;
}
diff --git a/src/cz/crcs/ectester/standalone/libs/OpensslLib.java b/src/cz/crcs/ectester/standalone/libs/OpensslLib.java
new file mode 100644
index 0000000..e558336
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/OpensslLib.java
@@ -0,0 +1,19 @@
+package cz.crcs.ectester.standalone.libs;
+
+import java.security.Provider;
+import java.util.Set;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class OpensslLib extends NativeECLibrary {
+ public OpensslLib() {
+ super("openssl_provider", "crypto");
+ }
+
+ @Override
+ native Provider createProvider();
+
+ @Override
+ public native Set<String> getCurves();
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
index 3530499..006a3b1 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile
+++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
@@ -1,32 +1,32 @@
ifeq ($(JAVA_HOME),)
-ifeq ($(OS),Windows_NT)
-which = $(shell where $1)
-else
-which = $(shell which $1)
-endif
-JAVAC ?= $(realpath $(call which,javac))
-JAVA_HOME = $(abspath $(dir $(JAVAC))..)
+ ifeq ($(OS),Windows_NT)
+ which = $(shell where $1)
+ else
+ which = $(shell which $1)
+ endif
+ JAVAC ?= $(realpath $(call which,javac))
+ JAVA_HOME = $(abspath $(dir $(JAVAC))..)
endif
ifneq ($(JAVA_HOME),)
-JNI_INCLUDEDIR ?= $(JAVA_HOME)/include
+ JNI_INCLUDEDIR ?= $(JAVA_HOME)/include
endif
ifeq ($(JNI_INCLUDEDIR),)
-$(error could not determine JNI include dir, try specifying either \
- JAVA_HOME or JNI_INCLUDEDIR)
+ $(error Could not determine JNI include dir. Try specifying either JAVA_HOME or JNI_INCLUDEDIR.)
endif
TARGETTRIPLET := $(shell $(CC) -dumpmachine)
+
ifeq ($(JNI_PLATFORM),)
-ifeq ($(findstring mingw,$(TARGETTRIPLET)),mingw)
-JNI_PLATFORM:= win32
-else
-ifeq ($(findstring linux,$(TARGETTRIPLET)),linux)
-JNI_PLATFORM:= linux
-# add more checks here
-endif
-endif
+ ifeq ($(findstring mingw,$(TARGETTRIPLET)),mingw)
+ JNI_PLATFORM:= win32
+ else
+ ifeq ($(findstring linux,$(TARGETTRIPLET)),linux)
+ JNI_PLATFORM:= linux
+ # add more checks here
+ endif
+ endif
endif
JNI_PLATFORMINCLUDEDIR ?= $(JNI_INCLUDEDIR)/$(JNI_PLATFORM)
@@ -36,13 +36,27 @@ LOCAL_LIBS = /usr/local/lib
CC?=gcc
CXX?=g++
+STRIP?=strip
-CFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
-CXXFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+LFLAGS+=-fPIC -shared
+CFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+CXXFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+DEBUG ?= 0
+
+ifeq ($(DEBUG), 1)
+ CFLAGS+=-g
+ LFLAGS+=-g
+ CXXFLAGS+=-g
+else
+ CFLAGS+=-O2
+ LFLAGS+=-O2
+ CXXFLAGS+=-O2
+endif
-all: tomcrypt_provider.so botan_provider.so
+all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so
+# Common utils
c_utils.o: c_utils.c
$(CC) $(CFLAGS) -c $<
@@ -50,18 +64,37 @@ cpp_utils.o: cpp_utils.cpp
$(CXX) $(CXXFLAGS) -c $<
+# OpenSSL shim
+openssl_provider.so: openssl.o c_utils.o
+ $(CC) $(LFLAGS) -o $@ $^ -L. $(shell pkg-config --libs openssl)
+
+openssl.o: openssl.c
+ $(CC) $(shell pkg-config --cflags openssl) $(CFLAGS) -c $<
+
+
+# Libtomcrypt shim
tomcrypt_provider.so: tomcrypt.o c_utils.o
- $(CC) -fPIC -g -shared -o $@ $^ -L. -ltommath -ltomcrypt
+ $(CC) $(LFLAGS) -o $@ $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt)
tomcrypt.o: tomcrypt.c
- $(CC) -DLTM_DESC $(CFLAGS) -c $<
+ $(CC) -DLTM_DESC $(shell pkg-config --cflags libtomcrypt) $(CFLAGS) -c $<
+# Botan-2 shim
botan_provider.so: botan.o cpp_utils.o
- $(CXX) -fPIC -g -shared -o $@ $^ -L. -L"$(LOCAL_LIBS)" -lbotan-2 -fstack-protector -m64 -pthread
+ $(CXX) $(LFLAGS) -o $@ $^ -L. $(shell pkg-config --libs botan-2)
botan.o: botan.cpp
- $(CXX) -I"$(LOCAL_INCLUDES)/botan-2" $(CFLAGS) -c $<
+ $(CXX) $(shell pkg-config --cflags botan-2) $(CXXFLAGS) -c $<
+
+
+# Crypto++ shim
+cryptopp_provider.so: cryptopp.o cpp_utils.o
+ $(CXX) $(LFLAGS) -o $@ $^ -L. $(shell pkg-config --libs libcrypto++)
+
+cryptopp.o: cryptopp.cpp
+ $(CXX) $(shell pkg-config --cflags libcrypto++) $(CXXFLAGS) -c $<
+
clean:
rm -rf *.o
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat
new file mode 100755
index 0000000..9b0d6f7
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat
@@ -0,0 +1,163 @@
+@if not defined _echo echo off
+setlocal EnableDelayedExpansion
+
+:: ENV variables respected:
+:: - JAVA_HOME
+:: - CC
+:: - USE_EXT_MSCNG
+:: - DEBUG
+
+:: See if we are cleaning.
+if "%1" == "clean" (
+ echo ** cleaning
+ del *.dll *.exp *.lib *.obj
+ exit
+)
+
+set TAB=
+
+
+:: Determine arch.
+reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL 2>&1 && (set ARCH=32& set ARCH_S=x86& set ARCH_VS=x86) || (set ARCH=64& set ARCH_S=x64& set ARCH_VS=amd64)
+
+echo ** ARCH%TAB%%TAB%%ARCH_S%
+
+
+:: Find a working visual studio environment.
+set found=0
+set vsw_path="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
+
+set vs_path=
+for /f "usebackq delims=" %%i in (`%vsw_path% -nologo -prerelease -latest -property installationPath`) do (
+ if exist "%%i\Common7\Tools\vsdevcmd.bat" (
+ echo ** VsDevCmd%TAB%%TAB%%%i\Common7\Tools\vsdevcmd.bat
+ call "%%i\Common7\Tools\vsdevcmd.bat" -no_logo -arch=%ARCH_VS%
+ if ERRORLEVEL 1 (
+ echo nope.
+ ) else (
+ set found=1
+ set vs_path=%%i
+ break
+ )
+ )
+)
+
+:: Test if we have a visual studio env.
+if %found% EQU 0 (
+ echo Working VsDevCmd not found.
+ exit /b 2
+)
+
+echo ** VS_PATH%TAB%%TAB%%vs_path%
+
+
+:: Try to find vcruntime.
+set vc_base=%vs_path%\VC\Tools\MSVC\
+if exist %vc_base% (
+ set vc_version=
+ for /f "delims=" %%i in ('dir /b /on "!vc_base!"') do (
+ set vc_version=%%i
+ )
+ echo ** VC_VERSION%TAB%!vc_version!
+ set vc_include=%vc_base%!vc_version!\include
+ set vc_lib=%vc_base%!vc_version!\lib\%ARCH_S%
+)
+
+
+:: Get the paths to Microsoft CNG SDK.
+set root_rel=..\..\..\..\..\..\..\
+set mscng_rel_include=ext\mscng\10\Include
+set mscng_rel_lib=ext\mscng\10\Lib
+
+pushd %root_rel%
+pushd %mscng_rel_include%
+set mscng_include=%CD%
+popd
+pushd %mscng_rel_lib%
+set mscng_lib=%CD%
+popd
+popd
+
+set mscng_lib_arch=%mscng_lib%\X%ARCH%
+
+echo ** CNG_INCLUDE%TAB%%mscng_include%
+echo ** CNG_LIB%TAB%%TAB%%mscng_lib_arch%
+
+
+:: Get the paths to Java JNI.
+if not defined JAVA_HOME (
+ set jva=
+ for /f "delims=" %%i in ('where javac') do (
+ set jva=%%~dpi
+ )
+ pushd !jva!\..
+ set JAVA_HOME=!CD!
+ popd
+)
+
+echo ** JAVA_HOME%TAB%%JAVA_HOME%
+
+set JNI_INCLUDEDIR=%JAVA_HOME%\include
+set JNI_PLATFORMINCLUDEDIR=%JNI_INCLUDEDIR%\win32
+set JNI_LIBDIR=%JAVA_HOME%\lib
+
+
+:: Setup binaries.
+if not defined CC (
+ set CC=cl.exe
+)
+
+echo ** CC%TAB%%TAB%%CC%
+
+
+:: Try to find uCRT.
+set ucrt_base=%ProgramFiles(x86)%\Windows Kits\10\
+if exist %ucrt_base% (
+ set ucrt_version=
+ for /f "delims=" %%i in ('dir /b /on "!ucrt_base!\Include"') do (
+ set ucrt_version=%%i
+ )
+ echo ** uCRT%TAB%%TAB%!ucrt_version!
+ set ucrt_include=%ucrt_base%Include\!ucrt_version!\ucrt
+ set ucrt_lib=%ucrt_base%Lib\!ucrt_version!
+ set ucrt_lib_arch=!ucrt_lib!\ucrt\%ARCH_S%
+)
+
+
+:: Setup INCLUDE paths.
+set INCLUDE_CLI=/I. /I"%JNI_INCLUDEDIR%" /I"%JNI_PLATFORMINCLUDEDIR%"
+
+if defined USE_EXT_MSCNG (
+ set INCLUDE_CLI=!INCLUDE_CLI! /I"%mscng_include%"
+)
+
+echo ** INCLUDE%TAB%%TAB%%INCLUDE%
+echo ** INCLUDE_CLI%TAB%%INCLUDE_CLI%
+
+
+:: Setup LIB paths.
+set LIBPATH=/LIBPATH:"%JNI_LIBDIR%"
+
+if defined USE_EXT_MSCNG (
+ set LIBPATH=!LIBPATH! /LIBPATH:"%mscng_lib_arch%"
+)
+
+echo ** LIB%TAB%%TAB%%LIB%
+echo ** LIBPATH%TAB%%TAB%%LIBPATH%
+
+
+:: Setup DEBUB options.
+set OTHER_CLI=
+if defined DEBUG (
+ set OTHER_CLI=/Od /Z7
+) else (
+ set OTHER_CLI=/O2
+)
+
+echo ** OTHER_CLI%TAB%%OTHER_CLI%
+echo.
+
+echo ^>^> %CC% /W2 /EHsc %OTHER_CLI% %INCLUDE_CLI% mscng.c c_utils.c bcrypt.lib jvm.lib /Femscng_provider.dll /LD /link %LIBPATH% /nologo
+echo.
+
+%CC% /W2 /EHsc %OTHER_CLI% %INCLUDE_CLI% mscng.c c_utils.c bcrypt.lib jvm.lib /Femscng_provider.dll /LD /link %LIBPATH% /nologo \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
index 22e5329..4cd4a9d 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
@@ -1,5 +1,6 @@
package cz.crcs.ectester.standalone.libs.jni;
+import cz.crcs.ectester.common.util.ByteUtil;
import org.bouncycastle.util.Arrays;
import java.math.BigInteger;
@@ -12,10 +13,12 @@ import java.security.spec.ECParameterSpec;
public abstract class NativeECPrivateKey implements ECPrivateKey {
private String algorithm;
private String format;
+ ECParameterSpec params;
- public NativeECPrivateKey(String algorithm, String format) {
+ public NativeECPrivateKey(String algorithm, String format, ECParameterSpec params) {
this.algorithm = algorithm;
this.format = format;
+ this.params = params;
}
@Override
@@ -28,14 +31,19 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
return format;
}
+ @Override
+ public ECParameterSpec getParams() {
+ return params;
+ }
+
+ public abstract byte[] getData();
+
private static class Raw extends NativeECPrivateKey {
- private byte[] keyData;
- private ECParameterSpec params;
+ byte[] keyData;
public Raw(byte[] keyData, ECParameterSpec params) {
- super("EC", "raw");
- this.keyData = keyData;
- this.params = params;
+ super("EC", "raw", params);
+ this.keyData = Arrays.clone(keyData);
}
@Override
@@ -48,9 +56,8 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
return Arrays.clone(keyData);
}
- @Override
- public ECParameterSpec getParams() {
- return params;
+ public byte[] getData() {
+ return getEncoded();
}
}
@@ -65,4 +72,57 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
super(keyData, params);
}
}
+
+ public static class Cryptopp extends Raw {
+ public Cryptopp(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
+ public static class Openssl extends Raw {
+ public Openssl(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
+ public static class Mscng extends Raw {
+ // 0 -> implicit (meta = curveName UTF16, header = full);
+ // 1 -> explicit (meta = null, header = full);
+ // 2 -> nist (meta = null, header = full)
+ private int flag;
+ private byte[] meta = null;
+ private byte[] header;
+ private byte[] x;
+ private byte[] y;
+
+ public Mscng(int flag, byte[] meta, byte[] header, byte[] x, byte[] y, byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ this.flag = flag;
+ this.meta = Arrays.clone(meta);
+ this.header = Arrays.clone(header);
+ this.x = Arrays.clone(x);
+ this.y = Arrays.clone(y);
+ }
+
+ public int getFlag() {
+ return flag;
+ }
+
+ public byte[] getMeta() {
+ return Arrays.clone(meta);
+ }
+
+ public byte[] getHeader() {
+ return Arrays.clone(header);
+ }
+
+ public byte[] getBlob() {
+ return ByteUtil.concatenate(header, x, y, keyData);
+ }
+
+ @Override
+ public byte[] getData() {
+ return getBlob();
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
index 8fc4747..ccf21c0 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
@@ -1,8 +1,10 @@
package cz.crcs.ectester.standalone.libs.jni;
+import cz.crcs.ectester.common.util.ByteUtil;
import cz.crcs.ectester.common.util.ECUtil;
import org.bouncycastle.util.Arrays;
+import javax.swing.event.AncestorEvent;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
@@ -13,10 +15,12 @@ import java.security.spec.ECPoint;
public abstract class NativeECPublicKey implements ECPublicKey {
private String algorithm;
private String format;
+ ECParameterSpec params;
- public NativeECPublicKey(String algorithm, String format) {
+ public NativeECPublicKey(String algorithm, String format, ECParameterSpec params) {
this.algorithm = algorithm;
this.format = format;
+ this.params = params;
}
@Override
@@ -29,14 +33,19 @@ public abstract class NativeECPublicKey implements ECPublicKey {
return format;
}
+ @Override
+ public ECParameterSpec getParams() {
+ return params;
+ }
+
+ public abstract byte[] getData();
+
private static class ANSIX962 extends NativeECPublicKey {
- private byte[] keyData;
- private ECParameterSpec params;
+ byte[] keyData;
public ANSIX962(byte[] keyData, ECParameterSpec params) {
- super("EC", "ANSI X9.62");
- this.keyData = keyData;
- this.params = params;
+ super("EC", "ANSI X9.62", params);
+ this.keyData = Arrays.clone(keyData);
}
@Override
@@ -49,9 +58,8 @@ public abstract class NativeECPublicKey implements ECPublicKey {
return Arrays.clone(keyData);
}
- @Override
- public ECParameterSpec getParams() {
- return params;
+ public byte[] getData() {
+ return ECUtil.toX962Uncompressed(getW(), params);
}
}
@@ -66,4 +74,57 @@ public abstract class NativeECPublicKey implements ECPublicKey {
super(keyData, params);
}
}
+
+ public static class Cryptopp extends ANSIX962 {
+ public Cryptopp(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
+ public static class Openssl extends ANSIX962 {
+ public Openssl(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
+ public static class Mscng extends ANSIX962 {
+ // 0 -> implicit (meta = curveName UTF16, header = full);
+ // 1 -> explicit (meta = null, header = full);
+ // 2 -> nist (meta = null, header = full)
+ private int flag;
+ private byte[] meta = null;
+ private byte[] header;
+ private byte[] x;
+ private byte[] y;
+
+ public Mscng(int flag, byte[] meta, byte[] header, byte[] x, byte[] y, ECParameterSpec params) {
+ super(ByteUtil.concatenate(new byte[]{0x04}, x, y), params);
+ this.flag = flag;
+ this.meta = Arrays.clone(meta);
+ this.header = Arrays.clone(header);
+ this.x = Arrays.clone(x);
+ this.y = Arrays.clone(y);
+ }
+
+ public int getFlag() {
+ return flag;
+ }
+
+ public byte[] getMeta() {
+ return Arrays.clone(meta);
+ }
+
+ public byte[] getHeader() {
+ return Arrays.clone(header);
+ }
+
+ public byte[] getBlob() {
+ return ByteUtil.concatenate(header, x, y);
+ }
+
+ @Override
+ public byte[] getData() {
+ return getBlob();
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
index 37c9add..4ed3469 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
@@ -5,19 +5,21 @@ import cz.crcs.ectester.common.util.ECUtil;
import javax.crypto.KeyAgreementSpi;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
+import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
+import java.security.spec.ECGenParameterSpec;
/**
* @author Jan Jancar johny@neuromancer.sk
*/
public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
- private ECPrivateKey privateKey;
- private ECPublicKey publicKey;
- private ECParameterSpec params;
+ ECPrivateKey privateKey;
+ ECPublicKey publicKey;
+ AlgorithmParameterSpec params;
@Override
protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
@@ -30,15 +32,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
}
@Override
- protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
- if (!(params instanceof ECParameterSpec)) {
- throw new InvalidAlgorithmParameterException();
- }
- engineInit(key, random);
- this.params = (ECParameterSpec) params;
- }
-
- @Override
protected Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException {
if (privateKey == null) {
throw new IllegalStateException("Not initialized");
@@ -59,13 +52,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
}
@Override
- protected byte[] engineGenerateSecret() throws IllegalStateException {
- byte[] pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), params.getCurve());
- byte[] privkey = ECUtil.toByteArray(privateKey.getS(), params.getCurve().getField().getFieldSize());
- return generateSecret(pubkey, privkey, params);
- }
-
- @Override
protected int engineGenerateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException {
byte[] secret = engineGenerateSecret();
if (sharedSecret.length < offset + secret.length) {
@@ -77,20 +63,70 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
@Override
protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException {
- throw new NoSuchAlgorithmException(algorithm);
+ // TODO: This is dangerous/not correct ! Need to actually implement KDF1 and KDF2 here probably. Or just pass it off to the libs through some different interface.
+ return new SecretKeySpec(engineGenerateSecret(), algorithm);
}
- abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+ private abstract static class SimpleKeyAgreementSpi extends NativeKeyAgreementSpi {
+
+ @Override
+ protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (!(params instanceof ECParameterSpec)) {
+ throw new InvalidAlgorithmParameterException();
+ }
+ engineInit(key, random);
+ this.params = params;
+ }
+
+ @Override
+ protected byte[] engineGenerateSecret() throws IllegalStateException {
+ byte[] pubkey;
+ if (publicKey instanceof NativeECPublicKey) {
+ pubkey = ((NativeECPublicKey) publicKey).getData();
+ } else {
+ pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), ((ECParameterSpec) params).getCurve());
+ }
+ byte[] privkey;
+ if (privateKey instanceof NativeECPrivateKey) {
+ privkey = ((NativeECPrivateKey) privateKey).getData();
+ } else {
+ privkey = ECUtil.toByteArray(privateKey.getS(), ((ECParameterSpec) params).getCurve().getField().getFieldSize());
+ }
+ return generateSecret(pubkey, privkey, (ECParameterSpec) params);
+ }
+
+ abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+ }
+
+ private abstract static class ExtendedKeyAgreementSpi extends NativeKeyAgreementSpi {
+
+ @Override
+ protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (!(params instanceof ECParameterSpec || params instanceof ECGenParameterSpec)) {
+ throw new InvalidAlgorithmParameterException();
+ }
+ engineInit(key, random);
+ this.params = params;
+ }
+
+ @Override
+ protected byte[] engineGenerateSecret() throws IllegalStateException {
+ return generateSecret(publicKey, privateKey, params);
+ }
+
+ abstract byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params);
+ }
- public static class TomCrypt extends NativeKeyAgreementSpi {
+ public static class TomCrypt extends SimpleKeyAgreementSpi {
@Override
native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
}
- public abstract static class Botan extends NativeKeyAgreementSpi {
+ public abstract static class Botan extends SimpleKeyAgreementSpi {
private String type;
+
public Botan(String type) {
this.type = type;
}
@@ -134,4 +170,73 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
super("ECDHwithSHA512KDF");
}
}
+
+ public abstract static class Cryptopp extends SimpleKeyAgreementSpi {
+ private String type;
+
+ public Cryptopp(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+ }
+
+ public static class CryptoppECDH extends Cryptopp {
+ public CryptoppECDH() {
+ super("ECDH");
+ }
+ }
+
+ public abstract static class Openssl extends SimpleKeyAgreementSpi {
+ private String type;
+
+ public Openssl(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+ }
+
+ public static class OpensslECDH extends Openssl {
+ public OpensslECDH() {
+ super("ECDH");
+ }
+ }
+
+ public abstract static class Mscng extends ExtendedKeyAgreementSpi {
+ private String type;
+
+ public Mscng(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params);
+ }
+
+ public static class MscngECDHwithSHA1KDF extends Mscng {
+ public MscngECDHwithSHA1KDF() {
+ super("ECDHwithSHA1KDF");
+ }
+ }
+
+ public static class MscngECDHwithSHA256KDF extends Mscng {
+ public MscngECDHwithSHA256KDF() {
+ super("ECDHwithSHA256KDF");
+ }
+ }
+
+ public static class MscngECDHwithSHA384KDF extends Mscng {
+ public MscngECDHwithSHA384KDF() {
+ super("ECDHwithSHA384KDF");
+ }
+ }
+
+ public static class MscngECDHwithSHA512KDF extends Mscng {
+ public MscngECDHwithSHA512KDF() {
+ super("ECDHwithSHA512KDF");
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
index 9461251..7ca013a 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
@@ -27,7 +27,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
@Override
public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException {
if (!paramsSupported(params)) {
- throw new InvalidAlgorithmParameterException("not supported.");
+ throw new InvalidAlgorithmParameterException("Not supported.");
}
this.params = params;
this.random = random;
@@ -41,8 +41,9 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
return generate(keysize, random);
} else if (useParams) {
return generate(params, random);
+ } else {
+ throw new IllegalStateException("Uninitialized KeyPair.");
}
- return null;
}
abstract boolean keysizeSupported(int keysize);
@@ -56,7 +57,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
public static class TomCrypt extends NativeKeyPairGeneratorSpi {
public TomCrypt() {
- initialize(256, new SecureRandom());
+ initialize(256, new SecureRandom());//TODO: maybe remove this default init?
}
@Override
@@ -77,7 +78,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
public Botan(String type) {
this.type = type;
- initialize(256, new SecureRandom());
+ initialize(256, new SecureRandom());//TODO: maybe remove this default init?
}
@Override
@@ -120,4 +121,92 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
super("ECGDSA");
}
}
+
+ public static abstract class Cryptopp extends NativeKeyPairGeneratorSpi {
+ private String type;
+
+ public Cryptopp(String type) {
+ this.type = type;
+ initialize(256, new SecureRandom());//TODO: maybe remove this default init?
+ }
+
+ @Override
+ native boolean keysizeSupported(int keysize);
+
+ @Override
+ native boolean paramsSupported(AlgorithmParameterSpec params);
+
+ @Override
+ native KeyPair generate(int keysize, SecureRandom random);
+
+ @Override
+ native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random);
+ }
+
+ public static class CryptoppECDH extends Cryptopp {
+
+ public CryptoppECDH() {
+ super("ECDH");
+ }
+ }
+
+ public static class CryptoppECDSA extends Cryptopp {
+
+ public CryptoppECDSA() {
+ super("ECDSA");
+ }
+ }
+
+ public static class Openssl extends NativeKeyPairGeneratorSpi {
+ public Openssl() {
+ initialize(256, new SecureRandom());
+ }
+
+ @Override
+ native boolean keysizeSupported(int keysize);
+
+ @Override
+ native boolean paramsSupported(AlgorithmParameterSpec params);
+
+ @Override
+ native KeyPair generate(int keysize, SecureRandom random);
+
+ @Override
+ native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random);
+ }
+
+ public static abstract class Mscng extends NativeKeyPairGeneratorSpi {
+ private String type;
+
+ public Mscng(String type) {
+ this.type = type;
+ initialize(256, new SecureRandom());
+ }
+
+ @Override
+ native boolean keysizeSupported(int keysize);
+
+ @Override
+ native boolean paramsSupported(AlgorithmParameterSpec params);
+
+ @Override
+ native KeyPair generate(int keysize, SecureRandom random);
+
+ @Override
+ native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random);
+ }
+
+ public static class MscngECDH extends Mscng {
+
+ public MscngECDH() {
+ super("ECDH");
+ }
+ }
+
+ public static class MscngECDSA extends Mscng {
+
+ public MscngECDSA() {
+ super("ECDSA");
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
index a0689d6..fef2930 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
@@ -12,10 +12,14 @@ public abstract class NativeProvider extends Provider {
public NativeProvider(String name, double version, String info) {
super(name, version, info);
- AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
+ if (System.getSecurityManager() == null) {
setup();
- return null;
- });
+ } else {
+ AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
+ setup();
+ return null;
+ });
+ }
}
abstract void setup();
@@ -39,4 +43,34 @@ public abstract class NativeProvider extends Provider {
@Override
native void setup();
}
+
+ public static class Cryptopp extends NativeProvider {
+
+ public Cryptopp(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ @Override
+ native void setup();
+ }
+
+ public static class Openssl extends NativeProvider {
+
+ public Openssl(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ @Override
+ native void setup();
+ }
+
+ public static class Mscng extends NativeProvider {
+
+ public Mscng(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ @Override
+ native void setup();
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
index b212697..b60f2c6 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
@@ -12,11 +12,11 @@ import java.security.spec.ECParameterSpec;
* @author Jan Jancar johny@neuromancer.sk
*/
public abstract class NativeSignatureSpi extends SignatureSpi {
- private ECPublicKey verifyKey;
- private ECPrivateKey signKey;
- private ECParameterSpec params;
+ ECPublicKey verifyKey;
+ ECPrivateKey signKey;
+ ECParameterSpec params;
- private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
@Override
protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
@@ -50,15 +50,6 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
buffer.write(b, off, len);
}
- @Override
- protected byte[] engineSign() throws SignatureException {
- return sign(buffer.toByteArray(), ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize()), params);
- }
-
- @Override
- protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
- return verify(sigBytes, buffer.toByteArray(), ECUtil.toX962Uncompressed(verifyKey.getW(), params), params);
- }
@Override
@Deprecated
@@ -72,11 +63,53 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
throw new UnsupportedOperationException("getParameter() not supported");
}
- abstract byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+ private abstract static class SimpleSignatureSpi extends NativeSignatureSpi {
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ byte[] privkey;
+ if (signKey instanceof NativeECPrivateKey) {
+ privkey = ((NativeECPrivateKey) signKey).getData();
+ } else {
+ privkey = ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize());
+ }
+ return sign(buffer.toByteArray(), privkey, params);
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ byte[] pubkey;
+ if (verifyKey instanceof NativeECPublicKey) {
+ pubkey = ((NativeECPublicKey) verifyKey).getData();
+ } else {
+ pubkey = ECUtil.toX962Uncompressed(verifyKey.getW(), params);
+ }
+ return verify(sigBytes, buffer.toByteArray(), pubkey, params);
+ }
- abstract boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ abstract byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
- public static class TomCryptRaw extends NativeSignatureSpi {
+ abstract boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ }
+
+ private abstract static class ExtendedSignatureSpi extends NativeSignatureSpi {
+
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ return sign(buffer.toByteArray(), signKey, params);
+ }
+
+ @Override
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ return verify(sigBytes, buffer.toByteArray(), verifyKey, params);
+ }
+
+ abstract byte[] sign(byte[] data, ECPrivateKey privkey, ECParameterSpec params);
+
+ abstract boolean verify(byte[] signature, byte[] data, ECPublicKey pubkey, ECParameterSpec params);
+ }
+
+ public static class TomCryptRaw extends SimpleSignatureSpi {
@Override
native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
@@ -85,7 +118,7 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
}
- public abstract static class Botan extends NativeSignatureSpi {
+ public abstract static class Botan extends SimpleSignatureSpi {
private String type;
public Botan(String type) {
@@ -224,4 +257,116 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
super("SHA512withECGDSA");
}
}
+
+ public abstract static class Cryptopp extends SimpleSignatureSpi {
+ private String type;
+
+ public Cryptopp(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ }
+
+ public static class CryptoppECDSAwithSHA1 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA1() {
+ super("SHA1withECDSA");
+ }
+ }
+
+ public static class CryptoppECDSAwithSHA224 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA224() {
+ super("SHA224withECDSA");
+ }
+ }
+
+ public static class CryptoppECDSAwithSHA256 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA256() {
+ super("SHA256withECDSA");
+ }
+ }
+
+ public static class CryptoppECDSAwithSHA384 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA384() {
+ super("SHA384withECDSA");
+ }
+ }
+
+ public static class CryptoppECDSAwithSHA512 extends Cryptopp {
+
+ public CryptoppECDSAwithSHA512() {
+ super("SHA512withECDSA");
+ }
+ }
+
+ public abstract static class Openssl extends SimpleSignatureSpi {
+ private String type;
+
+ public Openssl(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ }
+
+ public static class OpensslECDSAwithNONE extends Openssl {
+
+ public OpensslECDSAwithNONE() {
+ super("NONEwithECDSA");
+ }
+ }
+
+ public abstract static class Mscng extends ExtendedSignatureSpi {
+ private String type;
+
+ public Mscng(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] sign(byte[] data, ECPrivateKey privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, ECPublicKey pubkey, ECParameterSpec params);
+ }
+
+ public static class MscngECDSAwithSHA1 extends Mscng {
+
+ public MscngECDSAwithSHA1() {
+ super("SHA1withECDSA");
+ }
+ }
+
+ public static class MscngECDSAwithSHA256 extends Mscng {
+
+ public MscngECDSAwithSHA256() {
+ super("SHA256withECDSA");
+ }
+ }
+
+ public static class MscngECDSAwithSHA384 extends Mscng {
+
+ public MscngECDSAwithSHA384() {
+ super("SHA384withECDSA");
+ }
+ }
+
+ public static class MscngECDSAwithSHA512 extends Mscng {
+
+ public MscngECDSAwithSHA512() {
+ super("SHA512withECDSA");
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
index 8e666d6..d506ecd 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
+++ b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
@@ -1,6 +1,14 @@
#include "native.h"
#include <string>
-#include <botan/botan.h>
+
+#include <botan/lookup.h>
+#include <botan/version.h>
+#include <botan/parsing.h>
+#include <botan/init.h>
+#include <botan/rng.h>
+#include <botan/secmem.h>
+#include <botan/auto_rng.h>
+
#include <botan/ec_group.h>
#include <botan/ecc_key.h>
#include <botan/ecdsa.h>
@@ -12,11 +20,6 @@
static jclass provider_class;
-/*
- * Class: cz_crcs_ectester_standalone_libs_BotanLib
- * Method: createProvider
- * Signature: ()Ljava/security/Provider;
- */
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider(JNIEnv *env, jobject self) {
/* Create the custom provider. */
jclass local_provider_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeProvider$Botan");
@@ -36,166 +39,67 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createP
return env->NewObject(provider_class, init, name, version, info);
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
- * Method: setup
- * Signature: ()V
- */
JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Botan_setup(JNIEnv *env, jobject self){
jmethodID provider_put = env->GetMethodID(provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
- jstring ecdh = env->NewStringUTF("KeyPairGenerator.ECDH");
- jstring ecdh_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECDH");
- env->CallObjectMethod(self, provider_put, ecdh, ecdh_value);
-
- jstring ecdsa = env->NewStringUTF("KeyPairGenerator.ECDSA");
- jstring ecdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECDSA");
- env->CallObjectMethod(self, provider_put, ecdsa, ecdsa_value);
-
- jstring eckcdsa = env->NewStringUTF("KeyPairGenerator.ECKCDSA");
- jstring eckcdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECKCDSA");
- env->CallObjectMethod(self, provider_put, eckcdsa, eckcdsa_value);
-
- jstring ecgdsa = env->NewStringUTF("KeyPairGenerator.ECGDSA");
- jstring ecgdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECGDSA");
- env->CallObjectMethod(self, provider_put, ecgdsa, ecgdsa_value);
-
- jstring ecdh_ka = env->NewStringUTF("KeyAgreement.ECDH");
- jstring ecdh_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDH");
- env->CallObjectMethod(self, provider_put, ecdh_ka, ecdh_ka_value);
-
- jstring ecdh_sha1_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA1KDF");
- jstring ecdh_sha1_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA1KDF");
- env->CallObjectMethod(self, provider_put, ecdh_sha1_ka, ecdh_sha1_ka_value);
-
- jstring ecdh_sha224_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA224KDF");
- jstring ecdh_sha224_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA224KDF");
- env->CallObjectMethod(self, provider_put, ecdh_sha224_ka, ecdh_sha224_ka_value);
-
- jstring ecdh_sha256_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA256KDF");
- jstring ecdh_sha256_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA256KDF");
- env->CallObjectMethod(self, provider_put, ecdh_sha256_ka, ecdh_sha256_ka_value);
-
- jstring ecdh_sha384_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA384KDF");
- jstring ecdh_sha384_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA384KDF");
- env->CallObjectMethod(self, provider_put, ecdh_sha384_ka, ecdh_sha384_ka_value);
-
- jstring ecdh_sha512_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA512KDF");
- jstring ecdh_sha512_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA512KDF");
- env->CallObjectMethod(self, provider_put, ecdh_sha512_ka, ecdh_sha512_ka_value);
-
- jstring ecdsa_sig = env->NewStringUTF("Signature.NONEwithECDSA");
- jstring ecdsa_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithNONE");
- env->CallObjectMethod(self, provider_put, ecdsa_sig, ecdsa_sig_value);
-
- jstring ecdsa_sha1_sig = env->NewStringUTF("Signature.SHA1withECDSA");
- jstring ecdsa_sha1_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA1");
- env->CallObjectMethod(self, provider_put, ecdsa_sha1_sig, ecdsa_sha1_sig_value);
+ add_kpg(env, "ECDH", "BotanECDH", self, provider_put);
+ add_kpg(env, "ECDSA", "BotanECDSA", self, provider_put);
+ add_kpg(env, "ECKCDSA", "BotanECKCDSA", self, provider_put);
+ add_kpg(env, "ECGDSA", "BotanECGDSA", self, provider_put);
- jstring ecdsa_sha224_sig = env->NewStringUTF("Signature.SHA224withECDSA");
- jstring ecdsa_sha224_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA224");
- env->CallObjectMethod(self, provider_put, ecdsa_sha224_sig, ecdsa_sha224_sig_value);
+ add_ka(env, "ECDH", "BotanECDH", self, provider_put);
+ add_ka(env, "ECDHwithSHA1KDF", "BotanECDHwithSHA1KDF", self, provider_put);
+ add_ka(env, "ECDHwithSHA224KDF", "BotanECDHwithSHA224KDF", self, provider_put);
+ add_ka(env, "ECDHwithSHA256KDF", "BotanECDHwithSHA256KDF", self, provider_put);
+ add_ka(env, "ECDHwithSHA384KDF", "BotanECDHwithSHA384KDF", self, provider_put);
+ add_ka(env, "ECDHwithSHA512KDF", "BotanECDHwithSHA512KDF", self, provider_put);
- jstring ecdsa_sha256_sig = env->NewStringUTF("Signature.SHA256withECDSA");
- jstring ecdsa_sha256_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA256");
- env->CallObjectMethod(self, provider_put, ecdsa_sha256_sig, ecdsa_sha256_sig_value);
+ add_sig(env, "NONEwithECDSA", "BotanECDSAwithNONE", self, provider_put);
+ add_sig(env, "SHA1withECDSA", "BotanECDSAwithSHA1", self, provider_put);
+ add_sig(env, "SHA224withECDSA", "BotanECDSAwithSHA224", self, provider_put);
+ add_sig(env, "SHA256withECDSA", "BotanECDSAwithSHA256", self, provider_put);
+ add_sig(env, "SHA384withECDSA", "BotanECDSAwithSHA384", self, provider_put);
+ add_sig(env, "SHA512withECDSA", "BotanECDSAwithSHA512", self, provider_put);
- jstring ecdsa_sha384_sig = env->NewStringUTF("Signature.SHA384withECDSA");
- jstring ecdsa_sha384_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA384");
- env->CallObjectMethod(self, provider_put, ecdsa_sha384_sig, ecdsa_sha384_sig_value);
-
- jstring ecdsa_sha512_sig = env->NewStringUTF("Signature.SHA512withECDSA");
- jstring ecdsa_sha512_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECDSAwithSHA512");
- env->CallObjectMethod(self, provider_put, ecdsa_sha512_sig, ecdsa_sha512_sig_value);
+ add_sig(env, "NONEwithECKCDSA", "BotanECKCDSAwithNONE", self, provider_put);
+ add_sig(env, "SHA1withECKCDSA", "BotanECKCDSAwithSHA1", self, provider_put);
+ add_sig(env, "SHA224withECKCDSA", "BotanECKCDSAwithSHA224", self, provider_put);
+ add_sig(env, "SHA256withECKCDSA", "BotanECKCDSAwithSHA256", self, provider_put);
+ add_sig(env, "SHA384withECKCDSA", "BotanECKCDSAwithSHA384", self, provider_put);
+ add_sig(env, "SHA512withECKCDSA", "BotanECKCDSAwithSHA512", self, provider_put);
- jstring eckcdsa_sig = env->NewStringUTF("Signature.NONEwithECKCDSA");
- jstring eckcdsa_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithNONE");
- env->CallObjectMethod(self, provider_put, eckcdsa_sig, eckcdsa_sig_value);
-
- jstring eckcdsa_sha1_sig = env->NewStringUTF("Signature.SHA1withECKCDSA");
- jstring eckcdsa_sha1_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA1");
- env->CallObjectMethod(self, provider_put, eckcdsa_sha1_sig, eckcdsa_sha1_sig_value);
-
- jstring eckcdsa_sha224_sig = env->NewStringUTF("Signature.SHA224withECKCDSA");
- jstring eckcdsa_sha224_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA224");
- env->CallObjectMethod(self, provider_put, eckcdsa_sha224_sig, eckcdsa_sha224_sig_value);
-
- jstring eckcdsa_sha256_sig = env->NewStringUTF("Signature.SHA256withECKCDSA");
- jstring eckcdsa_sha256_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA256");
- env->CallObjectMethod(self, provider_put, eckcdsa_sha256_sig, eckcdsa_sha256_sig_value);
-
- jstring eckcdsa_sha384_sig = env->NewStringUTF("Signature.SHA384withECKCDSA");
- jstring eckcdsa_sha384_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA384");
- env->CallObjectMethod(self, provider_put, eckcdsa_sha384_sig, eckcdsa_sha384_sig_value);
-
- jstring eckcdsa_sha512_sig = env->NewStringUTF("Signature.SHA512withECKCDSA");
- jstring eckcdsa_sha512_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECKCDSAwithSHA512");
- env->CallObjectMethod(self, provider_put, eckcdsa_sha512_sig, eckcdsa_sha512_sig_value);
-
- jstring ecgdsa_sig = env->NewStringUTF("Signature.NONEwithECGDSA");
- jstring ecgdsa_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithNONE");
- env->CallObjectMethod(self, provider_put, ecgdsa_sig, ecgdsa_sig_value);
-
- jstring ecgdsa_sha1_sig = env->NewStringUTF("Signature.SHA1withECGDSA");
- jstring ecgdsa_sha1_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA1");
- env->CallObjectMethod(self, provider_put, ecgdsa_sha1_sig, ecgdsa_sha1_sig_value);
-
- jstring ecgdsa_sha224_sig = env->NewStringUTF("Signature.SHA224withECGDSA");
- jstring ecgdsa_sha224_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA224");
- env->CallObjectMethod(self, provider_put, ecgdsa_sha224_sig, ecgdsa_sha224_sig_value);
-
- jstring ecgdsa_sha256_sig = env->NewStringUTF("Signature.SHA256withECGDSA");
- jstring ecgdsa_sha256_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA256");
- env->CallObjectMethod(self, provider_put, ecgdsa_sha256_sig, ecgdsa_sha256_sig_value);
-
- jstring ecgdsa_sha384_sig = env->NewStringUTF("Signature.SHA384withECGDSA");
- jstring ecgdsa_sha384_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA384");
- env->CallObjectMethod(self, provider_put, ecgdsa_sha384_sig, ecgdsa_sha384_sig_value);
-
- jstring ecgdsa_sha512_sig = env->NewStringUTF("Signature.SHA512withECGDSA");
- jstring ecgdsa_sha512_sig_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$BotanECGDSAwithSHA512");
- env->CallObjectMethod(self, provider_put, ecgdsa_sha512_sig, ecgdsa_sha512_sig_value);
+ add_sig(env, "NONEwithECGDSA", "BotanECGDSAwithNONE", self, provider_put);
+ add_sig(env, "SHA1withECGDSA", "BotanECGDSAwithSHA1", self, provider_put);
+ add_sig(env, "SHA224withECGDSA", "BotanECGDSAwithSHA224", self, provider_put);
+ add_sig(env, "SHA256withECGDSA", "BotanECGDSAwithSHA256", self, provider_put);
+ add_sig(env, "SHA384withECGDSA", "BotanECGDSAwithSHA384", self, provider_put);
+ add_sig(env, "SHA512withECGDSA", "BotanECGDSAwithSHA512", self, provider_put);
init_classes(env, "Botan");
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_BotanLib
- * Method: getCurves
- * Signature: ()Ljava/util/Set;
- */
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self){
- jclass hash_set_class = env->FindClass("java/util/TreeSet");
+ jclass set_class = env->FindClass("java/util/TreeSet");
- jmethodID hash_set_ctr = env->GetMethodID(hash_set_class, "<init>", "()V");
- jmethodID hash_set_add = env->GetMethodID(hash_set_class, "add", "(Ljava/lang/Object;)Z");
+ jmethodID set_ctr = env->GetMethodID(set_class, "<init>", "()V");
+ jmethodID set_add = env->GetMethodID(set_class, "add", "(Ljava/lang/Object;)Z");
- jobject result = env->NewObject(hash_set_class, hash_set_ctr);
+ jobject result = env->NewObject(set_class, set_ctr);
const std::set<std::string>& curves = Botan::EC_Group::known_named_groups();
for (auto it = curves.begin(); it != curves.end(); ++it) {
std::string curve_name = *it;
jstring name_str = env->NewStringUTF(curve_name.c_str());
- env->CallBooleanMethod(result, hash_set_add, name_str);
+ env->CallBooleanMethod(result, set_add, name_str);
}
return result;
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
- * Method: keysizeSupported
- * Signature: (I)Z
- */
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported(JNIEnv *env, jobject self, jint keysize){
return JNI_TRUE;
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
- * Method: paramsSupported
- * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
- */
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_paramsSupported(JNIEnv *env, jobject self, jobject params){
if (params == NULL) {
return JNI_FALSE;
@@ -230,7 +134,7 @@ static jobject biginteger_from_bigint(JNIEnv *env, const Botan::BigInt& bigint)
jbyteArray bigint_array = env->NewByteArray(bigint_data.size());
jbyte * bigint_bytes = env->GetByteArrayElements(bigint_array, NULL);
std::copy(bigint_data.begin(), bigint_data.end(), bigint_bytes);
- env->ReleaseByteArrayElements(bigint_array, bigint_bytes, JNI_COMMIT);
+ env->ReleaseByteArrayElements(bigint_array, bigint_bytes, 0);
jmethodID biginteger_init = env->GetMethodID(biginteger_class, "<init>", "(I[B)V");
return env->NewObject(biginteger_class, biginteger_init, (jint) 1, bigint_array);
@@ -285,16 +189,14 @@ static Botan::EC_Group group_from_params(JNIEnv *env, jobject params) {
Botan::BigInt pi = bigint_from_biginteger(env, p);
Botan::BigInt ai = bigint_from_biginteger(env, a);
Botan::BigInt bi = bigint_from_biginteger(env, b);
- Botan::CurveGFp curve(pi, ai, bi);
Botan::BigInt gxi = bigint_from_biginteger(env, gx);
Botan::BigInt gyi = bigint_from_biginteger(env, gy);
- Botan::PointGFp generator(curve, gxi, gyi);
Botan::BigInt ni = bigint_from_biginteger(env, n);
Botan::BigInt hi(h);
- return Botan::EC_Group(curve, generator, ni, hi);
+ return Botan::EC_Group(pi, ai, bi, gxi, gyi, ni, hi);
} else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) {
jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
jstring name = (jstring) env->CallObjectMethod(params, get_name);
@@ -307,14 +209,13 @@ static Botan::EC_Group group_from_params(JNIEnv *env, jobject params) {
}
static jobject params_from_group(JNIEnv *env, Botan::EC_Group group) {
- const Botan::CurveGFp& curve = group.get_curve();
- jobject p = biginteger_from_bigint(env, curve.get_p());
+ jobject p = biginteger_from_bigint(env, group.get_p());
jmethodID fp_field_init = env->GetMethodID(fp_field_class, "<init>", "(Ljava/math/BigInteger;)V");
jobject fp_field = env->NewObject(fp_field_class, fp_field_init, p);
- jobject a = biginteger_from_bigint(env, curve.get_a());
- jobject b = biginteger_from_bigint(env, curve.get_b());
+ jobject a = biginteger_from_bigint(env, group.get_a());
+ jobject b = biginteger_from_bigint(env, group.get_b());
jmethodID elliptic_curve_init = env->GetMethodID(elliptic_curve_class, "<init>", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
jobject elliptic_curve = env->NewObject(elliptic_curve_class, elliptic_curve_init, fp_field, a, b);
@@ -365,12 +266,12 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
jobject ec_param_spec = params_from_group(env, group);
const Botan::PointGFp& pub_point = skey->public_point();
- std::vector<uint8_t> pub_data = Botan::unlock(Botan::EC2OSP(pub_point, Botan::PointGFp::UNCOMPRESSED));
+ std::vector<uint8_t> pub_data = pub_point.encode(Botan::PointGFp::UNCOMPRESSED);
jbyteArray pub_bytearray = env->NewByteArray(pub_data.size());
jbyte *pub_bytes = env->GetByteArrayElements(pub_bytearray, NULL);
std::copy(pub_data.begin(), pub_data.end(), pub_bytes);
- env->ReleaseByteArrayElements(pub_bytearray, pub_bytes, JNI_COMMIT);
+ env->ReleaseByteArrayElements(pub_bytearray, pub_bytes, 0);
jobject ec_pub_param_spec = env->NewLocalRef(ec_param_spec);
jmethodID ec_pub_init = env->GetMethodID(pubkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
@@ -382,7 +283,7 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
jbyteArray priv_bytearray = env->NewByteArray(priv_data.size());
jbyte *priv_bytes = env->GetByteArrayElements(priv_bytearray, NULL);
std::copy(priv_data.begin(), priv_data.end(), priv_bytes);
- env->ReleaseByteArrayElements(priv_bytearray, priv_bytes, JNI_COMMIT);
+ env->ReleaseByteArrayElements(priv_bytearray, priv_bytes, 0);
jobject ec_priv_param_spec = env->NewLocalRef(ec_param_spec);
jmethodID ec_priv_init = env->GetMethodID(privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
@@ -393,16 +294,11 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
return env->NewObject(keypair_class, keypair_init, pubkey, privkey);
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
- * Method: generate
- * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
- */
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random){
const std::set<std::string>& curves = Botan::EC_Group::known_named_groups();
for (auto it = curves.begin(); it != curves.end(); ++it) {
Botan::EC_Group curve_group = Botan::EC_Group(*it);
- size_t curve_size = curve_group.get_curve().get_p().bits();
+ size_t curve_size = curve_group.get_p_bits();
if (curve_size == keysize) {
//generate on this group. Even thou no default groups are present...
return generate_from_group(env, self, curve_group);
@@ -413,21 +309,11 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai
return NULL;
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
- * Method: generate
- * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
- */
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){
Botan::EC_Group curve_group = group_from_params(env, params);
return generate_from_group(env, self, curve_group);
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
- * Method: generateSecret
- * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
- */
JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Botan_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params){
Botan::EC_Group curve_group = group_from_params(env, params);
@@ -442,7 +328,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
jsize pubkey_length = env->GetArrayLength(pubkey);
jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL);
- Botan::PointGFp public_point = Botan::OS2ECP((uint8_t*) pubkey_data, pubkey_length, curve_group.get_curve());
+ Botan::PointGFp public_point = curve_group.OS2ECP((uint8_t*) pubkey_data, pubkey_length);
env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT);
Botan::ECDH_PublicKey pkey(curve_group, public_point);
@@ -461,19 +347,19 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
kdf = "Raw";
//key len unused
} else if (type_str == "ECDHwithSHA1KDF") {
- kdf = "KDF1(SHA-1)";
+ kdf = "KDF2(SHA-1)";
key_len = 20;
} else if (type_str == "ECDHwithSHA224KDF") {
- kdf = "KDF1(SHA-224)";
+ kdf = "KDF2(SHA-224)";
key_len = 28;
} else if (type_str == "ECDHwithSHA256KDF") {
- kdf = "KDF1(SHA-256)";
+ kdf = "KDF2(SHA-256)";
key_len = 32;
} else if (type_str == "ECDHwithSHA384KDF") {
- kdf = "KDF1(SHA-384)";
+ kdf = "KDF2(SHA-384)";
key_len = 48;
} else if (type_str == "ECDHwithSHA512KDF") {
- kdf = "KDF1(SHA-512)";
+ kdf = "KDF2(SHA-512)";
key_len = 64;
}
@@ -489,16 +375,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
jbyteArray result = env->NewByteArray(derived.size());
jbyte *result_data = env->GetByteArrayElements(result, NULL);
std::copy(derived.begin(), derived.end(), result_data);
- env->ReleaseByteArrayElements(result, result_data, JNI_COMMIT);
+ env->ReleaseByteArrayElements(result, result_data, 0);
return result;
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
- * Method: sign
- * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
- */
JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params){
Botan::EC_Group curve_group = group_from_params(env, params);
@@ -557,16 +438,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jbyteArray result = env->NewByteArray(sig.size());
jbyte *result_data = env->GetByteArrayElements(result, NULL);
std::copy(sig.begin(), sig.end(), result_data);
- env->ReleaseByteArrayElements(result, result_data, JNI_COMMIT);
+ env->ReleaseByteArrayElements(result, result_data, 0);
return result;
}
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
- * Method: verify
- * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
- */
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_verify(JNIEnv *env, jobject self, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params){
Botan::EC_Group curve_group = group_from_params(env, params);
@@ -579,7 +455,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
jsize pubkey_length = env->GetArrayLength(pubkey);
jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL);
- Botan::PointGFp public_point = Botan::OS2ECP((uint8_t*) pubkey_data, pubkey_length, curve_group.get_curve());
+ Botan::PointGFp public_point = curve_group.OS2ECP((uint8_t*) pubkey_data, pubkey_length);
env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT);
std::unique_ptr<Botan::EC_PublicKey> pkey;
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
index 336f4a1..6954c36 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
@@ -1,4 +1,5 @@
#include "c_utils.h"
+#define _ISOC99_SOURCE
#include <string.h>
jclass ec_parameter_spec_class;
@@ -21,7 +22,7 @@ void init_classes(JNIEnv *env, const char* lib_name) {
ecgen_parameter_spec_class = (*env)->NewGlobalRef(env, local_ecgen_parameter_spec_class);
const char *pubkey_base = "cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey$";
- char pubkey_class_name[strlen(pubkey_base) + strlen(lib_name) + 1];
+ char pubkey_class_name[2048] = { 0 }; //strlen(pubkey_base) + strlen(lib_name) + 1
pubkey_class_name[0] = 0;
strcat(pubkey_class_name, pubkey_base);
strcat(pubkey_class_name, lib_name);
@@ -30,7 +31,7 @@ void init_classes(JNIEnv *env, const char* lib_name) {
pubkey_class = (*env)->NewGlobalRef(env, local_pubkey_class);
const char *privkey_base = "cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey$";
- char privkey_class_name[strlen(privkey_base) + strlen(lib_name) + 1];
+ char privkey_class_name[2048] = { 0 }; //strlen(privkey_base) + strlen(lib_name) + 1
privkey_class_name[0] = 0;
strcat(privkey_class_name, privkey_base);
strcat(privkey_class_name, lib_name);
@@ -64,3 +65,12 @@ void throw_new(JNIEnv *env, const char *class, const char *message) {
jclass clazz = (*env)->FindClass(env, class);
(*env)->ThrowNew(env, clazz, message);
}
+
+void throw_new_var(JNIEnv *env, const char *class, const char *format, ...) {
+ char buffer[2048];
+ va_list args;
+ va_start(args, format);
+ int res = vsnprintf(buffer, 2048, format, args);
+ va_end(args);
+ throw_new(env, class, buffer);
+} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
index d925dfe..2e5fa1a 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
@@ -25,4 +25,22 @@ void init_classes(JNIEnv *env, const char* lib_name);
/**
* Throw a new exception of class with message.
*/
-void throw_new(JNIEnv *env, const char *class, const char *message); \ No newline at end of file
+void throw_new(JNIEnv *env, const char *class, const char *message);
+
+/**
+ * Throw a new exception of class, with formatted message.
+ */
+void throw_new_var(JNIEnv *env, const char *class, const char *format, ...);
+
+/**
+ * Some useful defines to init the provider.
+ */
+#define INIT_PROVIDER(env, provider_class) jmethodID provider_put = (*env)->GetMethodID(env, provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
+#define ADD_PROPERTY(env, self, base_name, base_class, prop_name, prop_class) do { \
+ jstring ec = (*env)->NewStringUTF(env, base_name prop_name); \
+ jstring ec_value = (*env)->NewStringUTF(env, base_class prop_class); \
+ (*env)->CallObjectMethod(env, self, provider_put, ec, ec_value); \
+ } while (0)
+#define ADD_KPG(env, self, kpg_name, kpg_class) ADD_PROPERTY(env, self, "KeyPairGenerator.", "cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$", kpg_name, kpg_class)
+#define ADD_KA(env, self, ka_name, ka_class) ADD_PROPERTY(env, self, "KeyAgreement.", "cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$", ka_name, ka_class)
+#define ADD_SIG(env, self, sig_name, sig_class) ADD_PROPERTY(env, self, "Signature.", "cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$", sig_name, sig_class) \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp
index cef4bfe..2e93a71 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp
+++ b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp
@@ -56,4 +56,28 @@ void init_classes(JNIEnv *env, std::string lib_name) {
void throw_new(JNIEnv *env, const std::string& klass, const std::string& message) {
jclass clazz = env->FindClass(klass.c_str());
env->ThrowNew(clazz, message.c_str());
+}
+
+static void add_provider_property(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method) {
+ jstring type_str = env->NewStringUTF(type.c_str());
+ jstring class_str = env->NewStringUTF(klass.c_str());
+ env->CallObjectMethod(provider, put_method, type_str, class_str);
+}
+
+void add_kpg(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method) {
+ const std::string full_type = "KeyPairGenerator." + type;
+ const std::string full_class = "cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$" + klass;
+ add_provider_property(env, full_type, full_class, provider, put_method);
+}
+
+void add_ka(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method) {
+ const std::string full_type = "KeyAgreement." + type;
+ const std::string full_class = "cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$" + klass;
+ add_provider_property(env, full_type, full_class, provider, put_method);
+}
+
+void add_sig(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method) {
+ const std::string full_type = "Signature." + type;
+ const std::string full_class = "cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$" + klass;
+ add_provider_property(env, full_type, full_class, provider, put_method);
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp
index bbca521..f647bd6 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp
+++ b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp
@@ -26,4 +26,10 @@ void init_classes(JNIEnv *env, std::string lib_name);
/**
* Throw a new exception of class with message.
*/
-void throw_new(JNIEnv *env, const std::string& klass, const std::string& message); \ No newline at end of file
+void throw_new(JNIEnv *env, const std::string& klass, const std::string& message);
+
+void add_kpg(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method);
+
+void add_ka(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method);
+
+void add_sig(JNIEnv *env, const std::string &type, const std::string &klass, jobject provider, jmethodID put_method); \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
new file mode 100644
index 0000000..0107d0d
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
@@ -0,0 +1,732 @@
+#include "native.h"
+
+#include <iostream>
+using std::cout;
+using std::cerr;
+using std::endl;
+
+#include <string>
+#include <sstream>
+using std::string;
+
+#include <stdexcept>
+using std::runtime_error;
+
+#include <cstdlib>
+using std::exit;
+
+#include "cryptopp/cryptlib.h"
+using CryptoPP::Exception;
+
+#include "cryptopp/config.h"
+using CryptoPP::byte;
+
+#include "cryptopp/osrng.h"
+using CryptoPP::AutoSeededRandomPool;
+using CryptoPP::AutoSeededX917RNG;
+
+#include "cryptopp/sha.h"
+using CryptoPP::SHA1;
+using CryptoPP::SHA224;
+using CryptoPP::SHA256;
+using CryptoPP::SHA384;
+using CryptoPP::SHA512;
+
+#include "cryptopp/aes.h"
+using CryptoPP::AES;
+
+#include "cryptopp/modarith.h"
+using CryptoPP::ModularArithmetic;
+
+#include "cryptopp/gf2n.h"
+using CryptoPP::PolynomialMod2;
+using CryptoPP::GF2NP;
+using CryptoPP::GF2NT;
+using CryptoPP::GF2NPP;
+
+#include "cryptopp/eccrypto.h"
+using CryptoPP::ECP;
+using CryptoPP::EC2N;
+using CryptoPP::ECDH;
+using CryptoPP::DL_GroupParameters_EC;
+using CryptoPP::ECDSA;
+
+#include "cryptopp/secblock.h"
+using CryptoPP::SecByteBlock;
+
+#include "cryptopp/oids.h"
+using CryptoPP::OID;
+
+// ASN1 is a namespace, not an object
+#include "cryptopp/asn.h"
+using namespace CryptoPP::ASN1;
+
+#include "cryptopp/integer.h"
+using CryptoPP::Integer;
+
+
+#include "cpp_utils.hpp"
+
+static jclass provider_class;
+
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider(JNIEnv *env, jobject self) {
+ /* Create the custom provider. */
+ jclass local_provider_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeProvider$Cryptopp");
+ provider_class = (jclass) env->NewGlobalRef(local_provider_class);
+
+ jmethodID init = env->GetMethodID(local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V");
+
+ std::string lib_name = "Crypto++";
+
+ int lib_version = CRYPTOPP_VERSION;
+ std::string info_str = std::to_string(lib_version);
+ std::stringstream ss;
+ ss << lib_name << " ";
+ ss << info_str[0];
+ for (int i = 1; i < info_str.size(); ++i) {
+ ss << "." << info_str[i];
+ }
+
+ jstring name = env->NewStringUTF(lib_name.c_str());
+ double version = lib_version / 100;
+ jstring info = env->NewStringUTF(ss.str().c_str());
+
+ return env->NewObject(provider_class, init, name, version, info);
+}
+
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Cryptopp_setup(JNIEnv *env, jobject self){
+ jmethodID provider_put = env->GetMethodID(provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+
+ add_kpg(env, "ECDH", "CryptoppECDH", self, provider_put);
+ add_kpg(env, "ECDSA", "CryptoppECDSA", self, provider_put);
+
+ add_ka(env, "ECDH", "CryptoppECDH", self, provider_put);
+
+ add_sig(env, "SHA1withECDSA", "CryptoppECDSAwithSHA1", self, provider_put);
+ add_sig(env, "SHA224withECDSA", "CryptoppECDSAwithSHA224", self, provider_put);
+ add_sig(env, "SHA256withECDSA", "CryptoppECDSAwithSHA256", self, provider_put);
+ add_sig(env, "SHA384withECDSA", "CryptoppECDSAwithSHA384", self, provider_put);
+ add_sig(env, "SHA512withECDSA", "CryptoppECDSAwithSHA512", self, provider_put);
+
+ init_classes(env, "Cryptopp");
+}
+
+template <class EC> static std::vector<OID> get_curve_oids() {
+ std::vector<OID> oids;
+ OID it = OID();
+ do {
+ it = DL_GroupParameters_EC<EC>::GetNextRecommendedParametersOID(it);
+ if (it == OID()) {
+ break;
+ }
+ oids.push_back(it);
+ } while (true);
+
+ return oids;
+}
+
+static std::vector<OID> get_all_curve_oids() {
+ std::vector<OID> ecp_oids = get_curve_oids<ECP>();
+ std::vector<OID> ec2n_oids = get_curve_oids<EC2N>();
+
+ std::vector<OID> all_oids;
+ all_oids.insert(all_oids.end(), ecp_oids.begin(), ecp_oids.end());
+ all_oids.insert(all_oids.end(), ec2n_oids.begin(), ec2n_oids.end());
+ return all_oids;
+}
+
+static std::string oid_to_str(const OID &oid) {
+ const std::vector<CryptoPP::word32>& oid_values = oid.GetValues();
+ std::stringstream ss;
+ for (size_t i = 0; i < oid_values.size(); ++i) {
+ if(i != 0)
+ ss << ".";
+ ss << std::to_string(oid_values[i]);
+ }
+ return ss.str();
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves(JNIEnv *env, jobject self){
+ jclass set_class = env->FindClass("java/util/TreeSet");
+
+ jmethodID set_ctr = env->GetMethodID(set_class, "<init>", "()V");
+ jmethodID set_add = env->GetMethodID(set_class, "add", "(Ljava/lang/Object;)Z");
+
+ jobject result = env->NewObject(set_class, set_ctr);
+
+ std::vector<OID> all_oids = get_all_curve_oids();
+
+ for (auto oid = all_oids.begin(); oid != all_oids.end(); ++oid) {
+ jstring name_str = env->NewStringUTF(oid_to_str(*oid).c_str());
+ env->CallBooleanMethod(result, set_add, name_str);
+ }
+
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported(JNIEnv *env, jobject self, jint keysize){
+ std::vector<OID> ecp_oids = get_curve_oids<ECP>();
+ for (auto oid = ecp_oids.begin(); oid != ecp_oids.end(); ++oid) {
+ DL_GroupParameters_EC<ECP> group(*oid);
+ if (((jint) group.GetCurve().GetField().MaxElementBitLength()) == keysize) {
+ return JNI_TRUE;
+ }
+ }
+
+ std::vector<OID> e2n_oids = get_curve_oids<EC2N>();
+ for (auto oid = e2n_oids.begin(); oid != e2n_oids.end(); ++oid) {
+ DL_GroupParameters_EC<EC2N> group(*oid);
+ if (((jint) group.GetCurve().FieldSize().ConvertToLong()) == keysize) {
+ return JNI_TRUE;
+ }
+ }
+ return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_paramsSupported(JNIEnv *env, jobject self, jobject params){
+ if (params == NULL) {
+ return JNI_FALSE;
+ }
+
+ if (env->IsInstanceOf(params, ec_parameter_spec_class)) {
+ // Any custom params should be supported.
+ return JNI_TRUE;
+ } else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) {
+ // Compare with OIDs I guess?
+ jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (jstring) env->CallObjectMethod(params, get_name);
+ const char *utf_name = env->GetStringUTFChars(name, NULL);
+ std::string str_name(utf_name);
+ env->ReleaseStringUTFChars(name, utf_name);
+
+ std::vector<OID> all_oids = get_all_curve_oids();
+ for (auto oid = all_oids.begin(); oid != all_oids.end(); ++oid) {
+ std::string oid_s = oid_to_str(*oid);
+ if (str_name == oid_s) {
+ return JNI_TRUE;
+ }
+ }
+ }
+ return JNI_FALSE;
+}
+
+static Integer integer_from_biginteger(JNIEnv *env, jobject bigint) {
+ jmethodID to_byte_array = env->GetMethodID(biginteger_class, "toByteArray", "()[B");
+
+ jbyteArray byte_array = (jbyteArray) env->CallObjectMethod(bigint, to_byte_array);
+ jsize byte_length = env->GetArrayLength(byte_array);
+ jbyte *byte_data = env->GetByteArrayElements(byte_array, NULL);
+ Integer result((byte *) byte_data, (size_t) byte_length);
+ env->ReleaseByteArrayElements(byte_array, byte_data, JNI_ABORT);
+ return result;
+}
+
+static jobject biginteger_from_integer(JNIEnv *env, const Integer &integer) {
+ jbyteArray byte_array = (jbyteArray) env->NewByteArray(integer.MinEncodedSize());
+
+ jbyte *bigint_bytes = env->GetByteArrayElements(byte_array, NULL);
+ integer.Encode((byte *) bigint_bytes, integer.MinEncodedSize());
+ env->ReleaseByteArrayElements(byte_array, bigint_bytes, 0);
+
+ jmethodID biginteger_init = env->GetMethodID(biginteger_class, "<init>", "(I[B)V");
+ return env->NewObject(biginteger_class, biginteger_init, (jint) 1, byte_array);
+}
+
+static jobject biginteger_from_polmod2(JNIEnv *env, const PolynomialMod2 &polmod) {
+ jmethodID biginteger_init = env->GetMethodID(biginteger_class, "<init>", "(I[B)V");
+
+ jbyteArray mod_array = env->NewByteArray(polmod.MinEncodedSize());
+ jbyte *mod_data = env->GetByteArrayElements(mod_array, NULL);
+ polmod.Encode((byte *) mod_data, polmod.MinEncodedSize());
+ env->ReleaseByteArrayElements(mod_array, mod_data, 0);
+
+ return env->NewObject(biginteger_class, biginteger_init, (jint) 1, mod_array);
+}
+
+static std::unique_ptr<DL_GroupParameters_EC<ECP>> fp_group_from_params(JNIEnv *env, jobject params) {
+ if (env->IsInstanceOf(params, ec_parameter_spec_class)) {
+ jmethodID get_curve = env->GetMethodID(ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = env->CallObjectMethod(params, get_curve);
+
+ jmethodID get_field = env->GetMethodID(elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = env->CallObjectMethod(elliptic_curve, get_field);
+
+ if (!env->IsInstanceOf(field, fp_field_class)) {
+ return nullptr;
+ }
+
+ jmethodID get_a = env->GetMethodID(elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject a = env->CallObjectMethod(elliptic_curve, get_a);
+ Integer ai = integer_from_biginteger(env, a);
+
+ jmethodID get_b = env->GetMethodID(elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject b = env->CallObjectMethod(elliptic_curve, get_b);
+ Integer bi = integer_from_biginteger(env, b);
+
+ jmethodID get_g = env->GetMethodID(ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g = env->CallObjectMethod(params, get_g);
+
+ jmethodID get_x = env->GetMethodID(point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = env->CallObjectMethod(g, get_x);
+
+ jmethodID get_y = env->GetMethodID(point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = env->CallObjectMethod(g, get_y);
+
+ jmethodID get_n = env->GetMethodID(ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject n = env->CallObjectMethod(params, get_n);
+ Integer ni = integer_from_biginteger(env, n);
+
+ jmethodID get_h = env->GetMethodID(ec_parameter_spec_class, "getCofactor", "()I");
+ jint h = env->CallIntMethod(params, get_h);
+ Integer hi(h);
+
+ jmethodID get_p = env->GetMethodID(fp_field_class, "getP", "()Ljava/math/BigInteger;");
+ jobject p = env->CallObjectMethod(field, get_p);
+ Integer pi = integer_from_biginteger(env, p);
+
+ ECP curve(pi, ai, bi);
+
+ Integer gxi = integer_from_biginteger(env, gx);
+ Integer gyi = integer_from_biginteger(env, gy);
+ ECP::Point g_point(gxi, gyi);
+
+ return std::make_unique<DL_GroupParameters_EC<ECP>>(curve, g_point, ni, hi);
+ } else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (jstring) env->CallObjectMethod(params, get_name);
+ const char *utf_name = env->GetStringUTFChars(name, NULL);
+ std::string str_name(utf_name);
+ env->ReleaseStringUTFChars(name, utf_name);
+
+ std::vector<OID> ecp_oids = get_curve_oids<ECP>();
+ for (auto oid = ecp_oids.begin(); oid != ecp_oids.end(); ++oid) {
+ std::string oid_s = oid_to_str(*oid);
+ if (str_name == oid_s) {
+ return std::make_unique<DL_GroupParameters_EC<ECP>>(*oid);
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+static std::unique_ptr<DL_GroupParameters_EC<EC2N>> f2m_group_from_params(JNIEnv *env, jobject params) {
+ if (env->IsInstanceOf(params, ec_parameter_spec_class)) {
+ jmethodID get_curve = env->GetMethodID(ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = env->CallObjectMethod(params, get_curve);
+
+ jmethodID get_field = env->GetMethodID(elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = env->CallObjectMethod(elliptic_curve, get_field);
+
+ if (!env->IsInstanceOf(field, f2m_field_class)) {
+ return nullptr;
+ }
+
+ jmethodID get_a = env->GetMethodID(elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject a = env->CallObjectMethod(elliptic_curve, get_a);
+ Integer ai = integer_from_biginteger(env, a);
+
+ jmethodID get_b = env->GetMethodID(elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject b = env->CallObjectMethod(elliptic_curve, get_b);
+ Integer bi = integer_from_biginteger(env, b);
+
+ jmethodID get_g = env->GetMethodID(ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g = env->CallObjectMethod(params, get_g);
+
+ jmethodID get_x = env->GetMethodID(point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = env->CallObjectMethod(g, get_x);
+
+ jmethodID get_y = env->GetMethodID(point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = env->CallObjectMethod(g, get_y);
+
+ jmethodID get_n = env->GetMethodID(ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject n = env->CallObjectMethod(params, get_n);
+ Integer ni = integer_from_biginteger(env, n);
+
+ jmethodID get_h = env->GetMethodID(ec_parameter_spec_class, "getCofactor", "()I");
+ jint h = env->CallIntMethod(params, get_h);
+ Integer hi(h);
+
+ jmethodID get_midterms = env->GetMethodID(f2m_field_class, "getMidTermsOfReductionPolynomial", "()[I");
+ jintArray midterms = (jintArray) env->CallObjectMethod(field, get_midterms);
+ jsize midterm_length = env->GetArrayLength(midterms);
+ jint *midterm_data = env->GetIntArrayElements(midterms, NULL);
+
+ jmethodID get_m = env->GetMethodID(f2m_field_class, "getM", "()I");
+ jint m = env->CallIntMethod(field, get_m);
+
+ std::unique_ptr<GF2NP> base_field;
+ if (midterm_length == 1) {
+ //trinomial, use GF2NT
+ base_field = std::make_unique<GF2NT>((unsigned int) m, (unsigned int) midterm_data[0], 0);
+ } else {
+ //pentanomial, use GF2NPP
+ base_field = std::make_unique<GF2NPP>((unsigned int) m, (unsigned int) midterm_data[0], (unsigned int) midterm_data[1], (unsigned int) midterm_data[2], 0);
+ }
+ env->ReleaseIntArrayElements(midterms, midterm_data, JNI_ABORT);
+
+ jmethodID to_byte_array = env->GetMethodID(biginteger_class, "toByteArray", "()[B");
+ jbyteArray a_array = (jbyteArray) env->CallObjectMethod(a, to_byte_array);
+ jsize a_length = env->GetArrayLength(a_array);
+ jbyte *a_data = env->GetByteArrayElements(a_array, NULL);
+
+ jbyteArray b_array = (jbyteArray) env->CallObjectMethod(b, to_byte_array);
+ jsize b_length = env->GetArrayLength(b_array);
+ jbyte *b_data = env->GetByteArrayElements(b_array, NULL);
+
+ EC2N curve(*base_field, EC2N::FieldElement((byte *) a_data, (size_t) a_length), EC2N::FieldElement((byte *) b_data, (size_t) b_length));
+ env->ReleaseByteArrayElements(a_array, a_data, JNI_ABORT);
+ env->ReleaseByteArrayElements(b_array, b_data, JNI_ABORT);
+
+ jbyteArray gx_array = (jbyteArray) env->CallObjectMethod(gx, to_byte_array);
+ jsize gx_length = env->GetArrayLength(gx_array);
+ jbyte *gx_data = env->GetByteArrayElements(gx_array, NULL);
+ PolynomialMod2 gxm((byte *) gx_data, (size_t) gx_length);
+ env->ReleaseByteArrayElements(gx_array, gx_data, JNI_ABORT);
+
+ jbyteArray gy_array = (jbyteArray) env->CallObjectMethod(gy, to_byte_array);
+ jsize gy_length = env->GetArrayLength(gy_array);
+ jbyte *gy_data = env->GetByteArrayElements(gy_array, NULL);
+ PolynomialMod2 gym((byte *) gy_data, (size_t) gy_length);
+ env->ReleaseByteArrayElements(gy_array, gy_data, JNI_ABORT);
+
+ EC2N::Point g_point(gxm, gym);
+
+ return std::make_unique<DL_GroupParameters_EC<EC2N>>(curve, g_point, ni, hi);
+ } else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (jstring) env->CallObjectMethod(params, get_name);
+ const char *utf_name = env->GetStringUTFChars(name, NULL);
+ std::string str_name(utf_name);
+ env->ReleaseStringUTFChars(name, utf_name);
+
+ std::vector<OID> e2n_oids = get_curve_oids<EC2N>();
+ for (auto oid = e2n_oids.begin(); oid != e2n_oids.end(); ++oid) {
+ std::string oid_s = oid_to_str(*oid);
+ if (str_name == oid_s) {
+ return std::make_unique<DL_GroupParameters_EC<EC2N>>(*oid);
+ }
+ }
+ }
+ return nullptr;
+}
+
+
+template <class EC> jobject finish_params(JNIEnv *env, jobject field, jobject a, jobject b, jobject gx, jobject gy, DL_GroupParameters_EC<EC> group) {
+ jmethodID point_init = env->GetMethodID(point_class, "<init>", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject g = env->NewObject(point_class, point_init, gx, gy);
+
+ jmethodID elliptic_curve_init = env->GetMethodID(elliptic_curve_class, "<init>", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject elliptic_curve = env->NewObject(elliptic_curve_class, elliptic_curve_init, field, a, b);
+
+ // Integer GetSubgroupOrder
+ // Integer GetCofactor
+ jobject order = biginteger_from_integer(env, group.GetSubgroupOrder());
+ jint cofactor = (jint) group.GetCofactor().ConvertToLong();
+
+ jmethodID ec_parameter_spec_init = env->GetMethodID(ec_parameter_spec_class, "<init>", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V");
+ return env->NewObject(ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, order, cofactor);
+}
+
+template <class EC> jobject params_from_group(JNIEnv *env, DL_GroupParameters_EC<EC> group) {
+ return NULL;
+}
+
+template <> jobject params_from_group<ECP>(JNIEnv *env, DL_GroupParameters_EC<ECP> group) {
+ ECP curve = group.GetCurve();
+ jmethodID fp_field_init = env->GetMethodID(fp_field_class, "<init>", "(Ljava/math/BigInteger;)V");
+ ModularArithmetic mod = curve.GetField();
+ jobject p = biginteger_from_integer(env, mod.GetModulus());
+ jobject a = biginteger_from_integer(env, curve.GetA());
+ jobject b = biginteger_from_integer(env, curve.GetB());
+
+ jobject field = env->NewObject(fp_field_class, fp_field_init, p);
+
+ ECP::Point gp = group.GetBasePrecomputation().GetBase(group.GetGroupPrecomputation());
+ jobject gx = biginteger_from_integer(env, gp.x);
+ jobject gy = biginteger_from_integer(env, gp.y);
+ return finish_params(env, field, a, b, gx, gy, group);
+}
+
+template <> jobject params_from_group<EC2N>(JNIEnv *env, DL_GroupParameters_EC<EC2N> group) {
+ EC2N curve = group.GetCurve();
+ PolynomialMod2 mod = curve.GetField().GetModulus();
+ int m = mod.Degree();
+ unsigned int coeff_count = mod.CoefficientCount();
+ jintArray ks;
+ int to_find;
+ int found = 0;
+ if (coeff_count == 3) {
+ //trinomial
+ ks = env->NewIntArray(1);
+ to_find = 1;
+ } else if (coeff_count == 5) {
+ //pentanomial
+ ks = env->NewIntArray(3);
+ to_find = 3;
+ }
+ jint *ks_data = env->GetIntArrayElements(ks, NULL);
+ for (int i = m - 1; i > 0 && found < to_find; --i) {
+ if (mod.GetCoefficient(i) == 1) {
+ ks_data[found++] = i;
+ }
+ }
+ env->ReleaseIntArrayElements(ks, ks_data, 0);
+
+ jmethodID f2m_field_init = env->GetMethodID(f2m_field_class, "<init>", "(I[I)V");
+ jobject field = env->NewObject(f2m_field_class, f2m_field_init, (jint) m, ks);
+
+ jobject a = biginteger_from_polmod2(env, curve.GetA());
+ jobject b = biginteger_from_polmod2(env, curve.GetB());
+
+ EC2N::Point gp = group.GetBasePrecomputation().GetBase(group.GetGroupPrecomputation());
+ jobject gx = biginteger_from_polmod2(env, gp.x);
+ jobject gy = biginteger_from_polmod2(env, gp.y);
+ return finish_params(env, field, a, b, gx, gy, group);
+}
+
+template <class EC> jobject generate_from_group(JNIEnv *env, DL_GroupParameters_EC<EC> group, jobject params) {
+ AutoSeededRandomPool rng;
+ typename ECDH<EC>::Domain ec_domain(group);
+ SecByteBlock priv(ec_domain.PrivateKeyLength()), pub(ec_domain.PublicKeyLength());
+
+ try {
+ ec_domain.GenerateKeyPair(rng, priv, pub);
+ } catch (Exception & ex) {
+ throw_new(env, "java/security/GeneralSecurityException", ex.what());
+ return NULL;
+ }
+
+ jbyteArray pub_bytearray = env->NewByteArray(pub.SizeInBytes());
+ jbyte *pub_bytes = env->GetByteArrayElements(pub_bytearray, NULL);
+ std::copy(pub.BytePtr(), pub.BytePtr()+pub.SizeInBytes(), pub_bytes);
+ env->ReleaseByteArrayElements(pub_bytearray, pub_bytes, 0);
+
+ jobject ec_pub_param_spec = env->NewLocalRef(params);
+ jmethodID ec_pub_init = env->GetMethodID(pubkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject pubkey = env->NewObject(pubkey_class, ec_pub_init, pub_bytearray, ec_pub_param_spec);
+
+ jbyteArray priv_bytearray = env->NewByteArray(priv.SizeInBytes());
+ jbyte *priv_bytes = env->GetByteArrayElements(priv_bytearray, NULL);
+ std::copy(priv.BytePtr(), priv.BytePtr()+priv.SizeInBytes(), priv_bytes);
+ env->ReleaseByteArrayElements(priv_bytearray, priv_bytes, 0);
+
+ jobject ec_priv_param_spec = env->NewLocalRef(params);
+ jmethodID ec_priv_init = env->GetMethodID(privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject privkey = env->NewObject(privkey_class, ec_priv_init, priv_bytearray, ec_priv_param_spec);
+
+ jmethodID keypair_init = env->GetMethodID(keypair_class, "<init>", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+
+ return env->NewObject(keypair_class, keypair_init, pubkey, privkey);
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random){
+ std::vector<OID> ecp_oids = get_curve_oids<ECP>();
+ for (auto oid = ecp_oids.begin(); oid != ecp_oids.end(); ++oid) {
+ DL_GroupParameters_EC<ECP> group(*oid);
+ if (((jint) group.GetCurve().GetField().MaxElementBitLength()) == keysize) {
+ jobject params = params_from_group(env, group);
+ return generate_from_group<ECP>(env, group, params);
+ }
+ }
+
+ std::vector<OID> e2n_oids = get_curve_oids<EC2N>();
+ for (auto oid = e2n_oids.begin(); oid != e2n_oids.end(); ++oid) {
+ DL_GroupParameters_EC<EC2N> group(*oid);
+ if ((jint) group.GetCurve().FieldSize().ConvertToLong() == keysize) {
+ jobject params = params_from_group(env, group);
+ return generate_from_group<EC2N>(env, group, params);
+ }
+ }
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random) {
+ std::unique_ptr<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params);
+ if (ecp_group == nullptr) {
+ std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params);
+ return generate_from_group<EC2N>(env, *ec2n_group, params);
+ } else {
+ return generate_from_group<ECP>(env, *ecp_group, params);
+ }
+ return NULL;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Cryptopp_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) {
+ jsize privkey_length = env->GetArrayLength(privkey);
+ jbyte *privkey_data = env->GetByteArrayElements(privkey, NULL);
+ SecByteBlock private_key((byte *) privkey_data, privkey_length);
+ env->ReleaseByteArrayElements(privkey, privkey_data, JNI_ABORT);
+
+ jsize pubkey_length = env->GetArrayLength(pubkey);
+ jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL);
+ SecByteBlock public_key((byte *) pubkey_data, pubkey_length);
+ env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT);
+
+ bool success;
+ std::unique_ptr<SecByteBlock> secret;
+ std::unique_ptr<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params);
+ if (ecp_group == nullptr) {
+ std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params);
+ ECDH<EC2N>::Domain dh_agreement(*ec2n_group);
+
+ try {
+ secret = std::make_unique<SecByteBlock>(dh_agreement.AgreedValueLength());
+ success = dh_agreement.Agree(*secret, private_key, public_key);
+ } catch (Exception & ex) {
+ throw_new(env, "java/security/GeneralSecurityException", ex.what());
+ return NULL;
+ }
+ } else {
+ ECDH<ECP>::Domain dh_agreement(*ecp_group);
+
+ try {
+ secret = std::make_unique<SecByteBlock>(dh_agreement.AgreedValueLength());
+ success = dh_agreement.Agree(*secret, private_key, public_key);
+ } catch (Exception & ex) {
+ throw_new(env, "java/security/GeneralSecurityException", ex.what());
+ return NULL;
+ }
+ }
+
+ jbyteArray result = env->NewByteArray(secret->size());
+ jbyte *result_data = env->GetByteArrayElements(result, NULL);
+ std::copy(secret->begin(), secret->end(), result_data);
+ env->ReleaseByteArrayElements(result, result_data, 0);
+
+ return result;
+}
+
+template <class EC, class H>
+jbyteArray sign_message(JNIEnv *env, DL_GroupParameters_EC<EC> group, jbyteArray data, const Integer & private_key_x) {
+ AutoSeededRandomPool prng;
+
+ typename ECDSA<EC, H>::PrivateKey pkey;
+ pkey.Initialize(group, private_key_x);
+ typename ECDSA<EC, H>::Signer signer(pkey);
+
+ std::string signature(signer.MaxSignatureLength(), 0);
+
+ jsize data_length = env->GetArrayLength(data);
+ jbyte *data_bytes = env->GetByteArrayElements(data, NULL);
+ size_t len = signer.SignMessage(prng, (byte *)data_bytes, data_length, (byte *)signature.c_str());
+ env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
+ signature.resize(len);
+
+ jbyteArray result = env->NewByteArray(len);
+ jbyte *result_bytes = env->GetByteArrayElements(result, NULL);
+ std::copy(signature.begin(), signature.end(), result_bytes);
+ env->ReleaseByteArrayElements(result, result_bytes, 0);
+
+ return result;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) {
+ jclass cryptopp_sig_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Cryptopp");
+ jfieldID type_id = env->GetFieldID(cryptopp_sig_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring) env->GetObjectField(self, type_id);
+ const char *type_data = env->GetStringUTFChars(type, NULL);
+ std::string type_str(type_data);
+ env->ReleaseStringUTFChars(type, type_data);
+
+ jsize privkey_length = env->GetArrayLength(privkey);
+ jbyte *privkey_data = env->GetByteArrayElements(privkey, NULL);
+ Integer private_key_x((byte *) privkey_data, (size_t) privkey_length);
+ env->ReleaseByteArrayElements(privkey, privkey_data, JNI_ABORT);
+
+ jbyteArray result;
+
+ std::unique_ptr<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params);
+ if (ecp_group == nullptr) {
+ std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params);
+ if (type_str.find("SHA1") != std::string::npos) {
+ result = sign_message<EC2N, SHA1>(env, *ec2n_group, data, private_key_x);
+ } else if (type_str.find("SHA224") != std::string::npos) {
+ result = sign_message<EC2N, SHA224>(env, *ec2n_group, data, private_key_x);
+ } else if (type_str.find("SHA256") != std::string::npos) {
+ result = sign_message<EC2N, SHA256>(env, *ec2n_group, data, private_key_x);
+ } else if (type_str.find("SHA384") != std::string::npos) {
+ result = sign_message<EC2N, SHA384>(env, *ec2n_group, data, private_key_x);
+ } else if (type_str.find("SHA512") != std::string::npos) {
+ result = sign_message<EC2N, SHA512>(env, *ec2n_group, data, private_key_x);
+ }
+ } else {
+ if (type_str.find("SHA1") != std::string::npos) {
+ result = sign_message<ECP, SHA1>(env, *ecp_group, data, private_key_x);
+ } else if (type_str.find("SHA224") != std::string::npos) {
+ result = sign_message<ECP, SHA224>(env, *ecp_group, data, private_key_x);
+ } else if (type_str.find("SHA256") != std::string::npos) {
+ result = sign_message<ECP, SHA256>(env, *ecp_group, data, private_key_x);
+ } else if (type_str.find("SHA384") != std::string::npos) {
+ result = sign_message<ECP, SHA384>(env, *ecp_group, data, private_key_x);
+ } else if (type_str.find("SHA512") != std::string::npos) {
+ result = sign_message<ECP, SHA512>(env, *ecp_group, data, private_key_x);
+ }
+ }
+
+ return result;
+}
+
+template <class EC, class H>
+jboolean verify_message(JNIEnv *env, DL_GroupParameters_EC<EC> group, jbyteArray data, jbyteArray signature, jbyteArray pubkey) {
+ typename EC::Point pkey_point;
+ jsize pubkey_length = env->GetArrayLength(pubkey);
+ jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL);
+ group.GetCurve().DecodePoint(pkey_point, (byte *)pubkey_data, pubkey_length);
+ env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT);
+
+ typename ECDSA<EC, H>::PublicKey pkey;
+ pkey.Initialize(group, pkey_point);
+ typename ECDSA<EC, H>::Verifier verifier(pkey);
+
+ jsize data_length = env->GetArrayLength(data);
+ jbyte *data_bytes = env->GetByteArrayElements(data, NULL);
+ jsize sig_length = env->GetArrayLength(signature);
+ jbyte *sig_bytes = env->GetByteArrayElements(signature, NULL);
+ bool result = verifier.VerifyMessage((byte *)data_bytes, data_length, (byte *)sig_bytes, sig_length);
+ env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
+ env->ReleaseByteArrayElements(signature, sig_bytes, JNI_ABORT);
+
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_verify(JNIEnv *env, jobject self, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params) {
+ jclass cryptopp_sig_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Cryptopp");
+ jfieldID type_id = env->GetFieldID(cryptopp_sig_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring) env->GetObjectField(self, type_id);
+ const char *type_data = env->GetStringUTFChars(type, NULL);
+ std::string type_str(type_data);
+ env->ReleaseStringUTFChars(type, type_data);
+
+ std::unique_ptr<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params);
+ if (ecp_group == nullptr) {
+ std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params);
+
+ if (type_str.find("SHA1") != std::string::npos) {
+ return verify_message<EC2N, SHA1>(env, *ec2n_group, data, signature, pubkey);
+ } else if (type_str.find("SHA224") != std::string::npos) {
+ return verify_message<EC2N, SHA224>(env, *ec2n_group, data, signature, pubkey);
+ } else if (type_str.find("SHA256") != std::string::npos) {
+ return verify_message<EC2N, SHA256>(env, *ec2n_group, data, signature, pubkey);
+ } else if (type_str.find("SHA384") != std::string::npos) {
+ return verify_message<EC2N, SHA384>(env, *ec2n_group, data, signature, pubkey);
+ } else if (type_str.find("SHA512") != std::string::npos) {
+ return verify_message<EC2N, SHA512>(env, *ec2n_group, data, signature, pubkey);
+ }
+ } else {
+ if (type_str.find("SHA1") != std::string::npos) {
+ return verify_message<ECP, SHA1>(env, *ecp_group, data, signature, pubkey);
+ } else if (type_str.find("SHA224") != std::string::npos) {
+ return verify_message<ECP, SHA224>(env, *ecp_group, data, signature, pubkey);
+ } else if (type_str.find("SHA256") != std::string::npos) {
+ return verify_message<ECP, SHA256>(env, *ecp_group, data, signature, pubkey);
+ } else if (type_str.find("SHA384") != std::string::npos) {
+ return verify_message<ECP, SHA384>(env, *ecp_group, data, signature, pubkey);
+ } else if (type_str.find("SHA512") != std::string::npos) {
+ return verify_message<ECP, SHA512>(env, *ecp_group, data, signature, pubkey);
+ }
+ }
+ // unreachable
+ return JNI_FALSE;
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c
new file mode 100644
index 0000000..16736d7
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c
@@ -0,0 +1,1210 @@
+#include "native.h"
+#include <windows.h>
+#include <bcrypt.h>
+
+#include "c_utils.h"
+
+#include <stdio.h>
+
+
+
+// BCRYPT and NT things.
+#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0)
+#define NT_FAILURE(status) !NT_SUCCESS(status)
+
+#define STATUS_SUCCESS 0x00000000
+#define STATUS_INVALID_SIGNATURE 0xC000A000
+
+typedef struct {
+ ULONG dwVersion; //Version of the structure
+ ECC_CURVE_TYPE_ENUM dwCurveType; //Supported curve types.
+ ECC_CURVE_ALG_ID_ENUM dwCurveGenerationAlgId; //For X.592 verification purposes, if we include Seed we will need to include the algorithm ID.
+ ULONG cbFieldLength; //Byte length of the fields P, A, B, X, Y.
+ ULONG cbSubgroupOrder; //Byte length of the subgroup.
+ ULONG cbCofactor; //Byte length of cofactor of G in E.
+ ULONG cbSeed; //Byte length of the seed used to generate the curve.
+} BCRYPT_ECC_PARAMETER_HEADER;
+
+//Provider things
+static jclass provider_class;
+
+#define KEYFLAG_IMPLICIT 0 //Mscng native key, over named curve
+#define KEYFLAG_EXPLICIT 1 //Mscng native key, over explicit ecc parameters
+#define KEYFLAG_NIST 2 //Mscng native key, over NIST parameters, custom ECDH/ECDSA_P* algo
+#define KEYFLAG_OTHER 3 //Other key, explicit ecc parameters
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self) {
+ jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng");
+ provider_class = (*env)->NewGlobalRef(env, local_provider_class);
+
+ jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V");
+
+ jstring name = (*env)->NewStringUTF(env, "Microsoft CNG");
+ double version = 1.0;
+
+ return (*env)->NewObject(env, provider_class, init, name, version, name);
+}
+
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup(JNIEnv *env, jobject self) {
+ INIT_PROVIDER(env, provider_class);
+
+ ADD_KPG(env, self, "ECDH", "MscngECDH");
+ ADD_KPG(env, self, "ECDSA", "MscngECDSA");
+
+ ADD_KA(env, self, "ECDHwithSHA1KDF", "MscngECDHwithSHA1KDF");
+ ADD_KA(env, self, "ECDHwithSHA256KDF", "MscngECDHwithSHA256KDF");
+ ADD_KA(env, self, "ECDHwithSHA384KDF", "MscngECDHwithSHA384KDF");
+ ADD_KA(env, self, "ECDHwithSHA512KDF", "MscngECDHwithSHA512KDF");
+
+ ADD_SIG(env, self, "SHA1withECDSA", "MscngECDSAwithSHA1");
+ ADD_SIG(env, self, "SHA256withECDSA", "MscngECDSAwithSHA256");
+ ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384");
+ ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112");
+
+ init_classes(env, "Mscng");
+}
+
+typedef struct {
+ LPCSTR name;
+ ULONG bits;
+} named_curve_t;
+
+static named_curve_t named_curves[] = {
+ {"curve25519", 256},
+ {"brainpoolP160r1", 160},
+ {"brainpoolP160t1", 160},
+ {"brainpoolP192r1", 192},
+ {"brainpoolP192t1", 192},
+ {"brainpoolP224r1", 224},
+ {"brainpoolP224t1", 224},
+ {"brainpoolP256r1", 256},
+ {"brainpoolP256t1", 256},
+ {"brainpoolP320r1", 320},
+ {"brainpoolP320t1", 320},
+ {"brainpoolP384r1", 384},
+ {"brainpoolP384t1", 384},
+ {"brainpoolP512r1", 512},
+ {"brainpoolP512t1", 512},
+ {"ec192wapi", 192},
+ {"nistP192", 192},
+ {"nistP224", 224},
+ {"nistP256", 256},
+ {"nistP384", 384},
+ {"nistP521", 521},
+ {"numsP256t1", 256},
+ {"numsP384t1", 384},
+ {"numsP512t1", 512},
+ {"secP160k1", 160},
+ {"secP160r1", 160},
+ {"secP160r2", 160},
+ {"secP192k1", 192},
+ {"secP192r1", 192},
+ {"secP224k1", 224},
+ {"secP224r1", 224},
+ {"secP256k1", 256},
+ {"secP256r1", 256},
+ {"secP384r1", 384},
+ {"secP521r1", 521},
+ {"wtls12", 224},
+ {"wtls7", 160},
+ {"wtls9", 160},
+ {"x962P192v1", 192},
+ {"x962P192v2", 192},
+ {"x962P192v3", 192},
+ {"x962P239v1", 239},
+ {"x962P239v2", 239},
+ {"x962P239v3", 239},
+ {"x962P256v1", 256}
+};
+
+static const named_curve_t* lookup_curve(const char *name) {
+ for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) {
+ if (strcmp(name, named_curves[i].name) == 0) {
+ return &named_curves[i];
+ }
+ }
+ return NULL;
+}
+
+static ULONG utf_16to8(NPSTR *out_buf, LPCWSTR in_str) {
+ INT result = WideCharToMultiByte(CP_UTF8, 0, in_str, -1, NULL, 0, NULL, NULL);
+ *out_buf = calloc(result, 1);
+ return WideCharToMultiByte(CP_UTF8, 0, in_str, -1, *out_buf, result, NULL, NULL);
+}
+
+static ULONG utf_8to16(NWPSTR *out_buf, LPCSTR in_str) {
+ INT result = MultiByteToWideChar(CP_UTF8, 0, in_str, -1, NULL, 0);
+ *out_buf = calloc(result * sizeof(WCHAR), 1);
+ return MultiByteToWideChar(CP_UTF8, 0, in_str, -1, *out_buf, result);
+}
+
+/**
+ * Convert Java String to UTF-16 NWPSTR null-terminated.
+ * Returns: Length of NWPSTR in bytes!
+ */
+static ULONG utf_strto16(NWPSTR *out_buf, JNIEnv *env, jobject str) {
+ jsize len = (*env)->GetStringLength(env, str);
+ *out_buf = calloc(len * sizeof(jchar) + 1, 1);
+ const jchar *chars = (*env)->GetStringChars(env, str, NULL);
+ memcpy(*out_buf, chars, len * sizeof(jchar));
+ (*env)->ReleaseStringChars(env, str, chars);
+ return len * sizeof(jchar);
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves(JNIEnv *env, jobject self) {
+ jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet");
+
+ jmethodID hash_set_ctr = (*env)->GetMethodID(env, hash_set_class, "<init>", "()V");
+ jmethodID hash_set_add = (*env)->GetMethodID(env, hash_set_class, "add", "(Ljava/lang/Object;)Z");
+
+ jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr);
+
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE handle;
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, BCRYPT_ECDH_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ return result;
+ }
+
+ ULONG bufSize;
+ if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptGetProperty(length only)\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return result;
+ }
+
+ BCRYPT_ECC_CURVE_NAMES *curves = (BCRYPT_ECC_CURVE_NAMES *)calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, (PBYTE)curves, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptGetProperty(whole)\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ free(curves);
+ return result;
+ }
+
+ for (size_t i = 0; i < curves->dwEccCurveNames; ++i) {
+ NPSTR curve_name;
+ ULONG len = utf_16to8(&curve_name, curves->pEccCurveNames[i]);
+ jstring c_name = (*env)->NewStringUTF(env, curve_name);
+ (*env)->CallBooleanMethod(env, result, hash_set_add, c_name);
+ free(curve_name);
+ }
+
+ free(curves);
+
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) {
+ switch (keysize) {
+ case 256:
+ case 384:
+ case 521:
+ return JNI_TRUE;
+ default:
+ return JNI_FALSE;
+ }
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported(JNIEnv *env, jobject self, jobject params) {
+ if (params == NULL) {
+ return JNI_FALSE;
+ }
+
+ if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (*env)->CallObjectMethod(env, params, get_name);
+ const char *utf_name = (*env)->GetStringUTFChars(env, name, NULL);
+ const named_curve_t *curve = lookup_curve(utf_name);
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ return curve == NULL ? JNI_FALSE : JNI_TRUE;
+ } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject curve = (*env)->CallObjectMethod(env, params, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, curve, get_field);
+
+ if ((*env)->IsInstanceOf(env, field, fp_field_class)) {
+ return JNI_TRUE;
+ } else {
+ return JNI_FALSE;
+ }
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jobject bytes_to_biginteger(JNIEnv *env, PBYTE bytes, int len) {
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "<init>", "(I[B)V");
+ jbyteArray byte_array = (*env)->NewByteArray(env, len);
+ jbyte *data = (*env)->GetByteArrayElements(env, byte_array, NULL);
+ memcpy(data, bytes, len);
+ (*env)->ReleaseByteArrayElements(env, byte_array, data, 0);
+ jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, byte_array);
+ return result;
+}
+
+static void biginteger_to_bytes(JNIEnv *env, jobject bigint, PBYTE bytes, ULONG len) {
+ jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
+
+ jbyteArray byte_array = (jbyteArray)(*env)->CallObjectMethod(env, bigint, to_byte_array);
+ jsize byte_length = (*env)->GetArrayLength(env, byte_array);
+ jbyte *byte_data = (*env)->GetByteArrayElements(env, byte_array, NULL);
+ memcpy(bytes, &byte_data[byte_length - len], len);
+ (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT);
+}
+
+static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLength) {
+ //
+ // BCRYPT_ECCFULLKEY_BLOB header
+ // P[cbFieldLength] Prime specifying the base field.
+ // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p
+ // B[cbFieldLength] Coefficient B of the equation y^2 = x^3 + A*x + B mod p
+ // Gx[cbFieldLength] X-coordinate of the base point.
+ // Gy[cbFieldLength] Y-coordinate of the base point.
+ // n[cbSubgroupOrder] Order of the group generated by G = (x,y)
+ // h[cbCofactor] Cofactor of G in E.
+ // S[cbSeed] Seed of the curve.
+
+ BCRYPT_ECCFULLKEY_BLOB *header = (BCRYPT_ECCFULLKEY_BLOB*)eccParams;
+ PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECCFULLKEY_BLOB)];
+
+ //cbFieldLength
+ PBYTE P = paramsStart;
+ PBYTE A = P + header->cbFieldLength;
+ PBYTE B = A + header->cbFieldLength;
+ PBYTE GX = B + header->cbFieldLength;
+ PBYTE GY = GX + header->cbFieldLength;
+
+ //cbSubgroupOrder
+ PBYTE N = GY + header->cbFieldLength;
+
+ //cbCofactor
+ PBYTE H = N + header->cbSubgroupOrder;
+
+ //cbSeed
+ PBYTE S = H + header->cbCofactor;
+
+ *paramLength = sizeof(BCRYPT_ECCFULLKEY_BLOB) + 5 * header->cbFieldLength + header->cbSubgroupOrder + header->cbCofactor + header->cbSeed;
+
+ jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength);
+
+ jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "<init>", "(Ljava/math/BigInteger;)V");
+ jobject field = (*env)->NewObject(env, fp_field_class, fp_field_init, p_int);
+
+ jobject a_int = bytes_to_biginteger(env, A, header->cbFieldLength);
+ jobject b_int = bytes_to_biginteger(env, B, header->cbFieldLength);
+
+ jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "<init>", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject elliptic_curve = (*env)->NewObject(env, elliptic_curve_class, elliptic_curve_init, field, a_int, b_int);
+
+ jobject gx_int = bytes_to_biginteger(env, GX, header->cbFieldLength);
+ jobject gy_int = bytes_to_biginteger(env, GY, header->cbFieldLength);
+
+ jmethodID point_init = (*env)->GetMethodID(env, point_class, "<init>", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int);
+
+ jobject n_int = bytes_to_biginteger(env, N, header->cbSubgroupOrder);
+
+ jobject h_int = bytes_to_biginteger(env, H, header->cbCofactor);
+ jmethodID bigint_to_int = (*env)->GetMethodID(env, biginteger_class, "intValue", "()I");
+ jint cof = (*env)->CallIntMethod(env, h_int, bigint_to_int);
+
+ jmethodID ec_parameter_spec_init = (*env)->GetMethodID(env, ec_parameter_spec_class, "<init>", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V");
+ return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n_int, cof);
+}
+
+static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) {
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = (*env)->CallObjectMethod(env, params, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, elliptic_curve, get_field);
+
+ jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I");
+ jint bits = (*env)->CallIntMethod(env, field, get_bits);
+ jint bytes = (bits + 7) / 8;
+
+ jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a);
+
+ jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b);
+
+ jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;");
+ jobject p = (*env)->CallObjectMethod(env, field, get_p);
+
+ jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g = (*env)->CallObjectMethod(env, params, get_g);
+
+ jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = (*env)->CallObjectMethod(env, g, get_x);
+
+ jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = (*env)->CallObjectMethod(env, g, get_y);
+
+ jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject n = (*env)->CallObjectMethod(env, params, get_n);
+
+ jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I");
+ jint h = (*env)->CallIntMethod(env, params, get_h);
+
+ jmethodID get_bitlength = (*env)->GetMethodID(env, biginteger_class, "bitLength", "()I");
+ jint order_bits = (*env)->CallIntMethod(env, n, get_bitlength);
+ jint order_bytes = (order_bits + 7) / 8;
+
+ // header_size + 5*bytes + order_bytes + cof_size + 0
+ ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5 * bytes + order_bytes + 1 + 0;
+ *curve = calloc(bufSize, 1);
+ BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve;
+ header->dwVersion = 1;
+ header->dwCurveType = 1; //1 -> Prime short Weierstrass, 2 -> Prime Twisted Edwards, 3 -> Montgomery
+ header->dwCurveGenerationAlgId = 0;
+ header->cbFieldLength = bytes;
+ header->cbSubgroupOrder = order_bytes;
+ header->cbCofactor = 1;
+ header->cbSeed = 0;
+
+ PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)];
+
+ biginteger_to_bytes(env, p, paramsStart, bytes);
+ biginteger_to_bytes(env, a, paramsStart + bytes, bytes);
+ biginteger_to_bytes(env, b, paramsStart + 2 * bytes, bytes);
+ biginteger_to_bytes(env, gx, paramsStart + 3 * bytes, bytes);
+ biginteger_to_bytes(env, gy, paramsStart + 4 * bytes, bytes);
+ biginteger_to_bytes(env, n, paramsStart + 5 * bytes, order_bytes);
+ PBYTE cof_ptr = (PBYTE)(paramsStart + 5 * bytes + order_bytes);
+ *cof_ptr = (BYTE)h;
+ return bufSize;
+}
+
+static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, jint *keyflag, NWPSTR *curve_name, LPCWSTR algo, jobject params) {
+ NTSTATUS status;
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ return 0;
+ }
+ ULONG result = 0;
+ if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (*env)->CallObjectMethod(env, params, get_name);
+ jint utf_length = (*env)->GetStringUTFLength(env, name);
+ PUCHAR chars = calloc(utf_length + 1, 1);
+ (*env)->GetStringUTFRegion(env, name, 0, utf_length, chars);
+ const named_curve_t *curve = lookup_curve(chars);
+ ULONG ret = utf_8to16(curve_name, chars);
+ if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, (PUCHAR)*curve_name, ret * sizeof(WCHAR), 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status);
+ return 0;
+ }
+ free(chars);
+ result = curve->bits;
+ *keyflag = KEYFLAG_IMPLICIT;
+ } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ PBYTE curve;
+ ULONG curveLen = create_curve(env, params, &curve);
+ if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status);
+ return 0;
+ }
+ free(curve);
+
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = (*env)->CallObjectMethod(env, params, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, elliptic_curve, get_field);
+
+ jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I");
+ jint bits = (*env)->CallIntMethod(env, field, get_bits);
+ result = bits;
+ *keyflag = KEYFLAG_EXPLICIT;
+ *curve_name = NULL;
+ }
+ return result;
+}
+
+static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPCWSTR curve) {
+ NTSTATUS status;
+ ULONG bufSize = 0;
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status);
+ return NULL;
+ }
+ if (bufSize == 0) {
+ printf("buf 0\n");
+ return NULL;
+ }
+
+ PBYTE fullBuf = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, fullBuf, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status);
+ free(fullBuf);
+ return NULL;
+ }
+
+ ULONG paramLength;
+ jobject ec_priv_param_spec = create_ec_param_spec(env, fullBuf, &paramLength);
+
+ // fullBuf looks like:
+ // BCRYPT_ECCFULLKEY_BLOB header
+ // P[cbFieldLength] Prime specifying the base field.
+ // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p
+ // B[cbFieldLength] Coefficient B of the equation y^2 = x^3 + A*x + B mod p
+ // Gx[cbFieldLength] X-coordinate of the base point.
+ // Gy[cbFieldLength] Y-coordinate of the base point.
+ // n[cbSubgroupOrder] Order of the group generated by G = (x,y)
+ // h[cbCofactor] Cofactor of G in E.
+ // S[cbSeed] Seed of the curve.
+ // Qx[cbFieldLength] X-coordinate of the public point.
+ // Qy[cbFieldLength] Y-coordinate of the public point.
+ // d[cbSubgroupOrder] Private key.
+ BCRYPT_ECCFULLKEY_BLOB *privHeader = (BCRYPT_ECCFULLKEY_BLOB*)fullBuf;
+ PBYTE priv_x = &fullBuf[paramLength];
+ PBYTE priv_y = priv_x + privHeader->cbFieldLength;
+ PBYTE priv = priv_y + privHeader->cbFieldLength;
+
+
+ jbyteArray meta_bytes = NULL;
+ jbyteArray header_bytes = NULL;
+ switch (flag) {
+ case 0: {
+ // meta = curve
+ jint meta_len = (wcslen(curve) + 1) * sizeof(WCHAR);
+ meta_bytes = (*env)->NewByteArray(env, meta_len);
+ jbyte *meta_data = (*env)->GetByteArrayElements(env, meta_bytes, NULL);
+ memcpy(meta_data, curve, meta_len);
+ (*env)->ReleaseByteArrayElements(env, meta_bytes, meta_data, 0);
+ }
+ case 1:
+ case 2: {
+ // meta = null
+ // header = full
+ header_bytes = (*env)->NewByteArray(env, paramLength);
+ jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL);
+ memcpy(header_data, fullBuf, paramLength);
+ (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0);
+ break;
+ }
+ default:
+ // header = small
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, length only)\n", status);
+ free(fullBuf);
+ return NULL;
+ }
+ if (bufSize == 0) {
+ printf("buf 0\n");
+ free(fullBuf);
+ return NULL;
+ }
+ PBYTE smallBuf = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, smallBuf, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, whole)\n", status);
+ free(fullBuf);
+ free(smallBuf);
+ return NULL;
+ }
+ // smallBuf looks like:
+ // BCRYPT_ECCKEY_BLOB header
+ // Qx[cbFieldLength] X-coordinate of the public point.
+ // Qy[cbFieldLength] Y-coordinate of the public point.
+ // d[cbSubgroupOrder] Private key.
+ header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB));
+ jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL);
+ memcpy(header_data, smallBuf, sizeof(BCRYPT_ECCKEY_BLOB));
+ (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0);
+ free(smallBuf);
+ break;
+ }
+
+ jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength);
+ jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL);
+ memcpy(x_data, priv_x, privHeader->cbFieldLength);
+ (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0);
+
+ jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength);
+ jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL);
+ memcpy(y_data, priv_y, privHeader->cbFieldLength);
+ (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0);
+
+ jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbSubgroupOrder);
+ jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
+ memcpy(key_priv, priv, privHeader->cbSubgroupOrder);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
+
+ free(fullBuf);
+
+ jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "<init>", "(I[B[B[B[B[BLjava/security/spec/ECParameterSpec;)V");
+ return (*env)->NewObject(env, privkey_class, ec_priv_init, flag, meta_bytes, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec);
+}
+
+static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPCWSTR curve) {
+ NTSTATUS status;
+ ULONG bufSize = 0;
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status);
+ return NULL;
+ }
+ if (bufSize == 0) {
+ printf("err0\n");
+ return NULL;
+ }
+
+ PBYTE fullBuf = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, fullBuf, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status);
+ return NULL;
+ }
+
+ ULONG paramLength;
+ jobject ec_pub_param_spec = create_ec_param_spec(env, fullBuf, &paramLength);
+
+ // fullBuf looks like:
+ // BCRYPT_ECCFULLKEY_BLOB header
+ // P[cbFieldLength] Prime specifying the base field.
+ // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p
+ // B[cbFieldLength] Coefficient B of the equation y^2 = x^3 + A*x + B mod p
+ // Gx[cbFieldLength] X-coordinate of the base point.
+ // Gy[cbFieldLength] Y-coordinate of the base point.
+ // n[cbSubgroupOrder] Order of the group generated by G = (x,y)
+ // h[cbCofactor] Cofactor of G in E.
+ // S[cbSeed] Seed of the curve.
+ // Qx[cbFieldLength] X-coordinate of the public point.
+ // Qy[cbFieldLength] Y-coordinate of the public point.
+ BCRYPT_ECCFULLKEY_BLOB *pubHeader = (BCRYPT_ECCFULLKEY_BLOB*)fullBuf;
+ PBYTE pub_x = &fullBuf[paramLength];
+ PBYTE pub_y = pub_x + pubHeader->cbFieldLength;
+
+ jbyteArray meta_bytes = NULL;
+ jbyteArray header_bytes = NULL;
+ switch (flag) {
+ case 0: {
+ // meta = curve
+ jint meta_len = (wcslen(curve) + 1) * sizeof(WCHAR);
+ meta_bytes = (*env)->NewByteArray(env, meta_len);
+ jbyte *meta_data = (*env)->GetByteArrayElements(env, meta_bytes, NULL);
+ memcpy(meta_data, curve, meta_len);
+ (*env)->ReleaseByteArrayElements(env, meta_bytes, meta_data, 0);
+ }
+ case 1:
+ case 2: {
+ header_bytes = (*env)->NewByteArray(env, paramLength);
+ jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL);
+ memcpy(header_data, pubHeader, paramLength);
+ (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0);
+ break;
+ }
+ default:
+ // header = small
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, length only)\n", status);
+ free(fullBuf);
+ return NULL;
+ }
+ if (bufSize == 0) {
+ printf("buf 0\n");
+ free(fullBuf);
+ return NULL;
+ }
+ PBYTE smallBuf = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, smallBuf, bufSize, &bufSize, 0))) {
+ wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, whole)\n", status);
+ free(fullBuf);
+ free(smallBuf);
+ return NULL;
+ }
+ // smallBuf looks like:
+ // BCRYPT_ECCKEY_BLOB header
+ // Qx[cbFieldLength] X-coordinate of the public point.
+ // Qy[cbFieldLength] Y-coordinate of the public point.
+ header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB));
+ jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL);
+ memcpy(header_data, smallBuf, sizeof(BCRYPT_ECCKEY_BLOB));
+ (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0);
+ free(smallBuf);
+ break;
+ }
+
+ jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength);
+ jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL);
+ memcpy(x_data, pub_x, pubHeader->cbFieldLength);
+ (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0);
+
+ jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength);
+ jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL);
+ memcpy(y_data, pub_y, pubHeader->cbFieldLength);
+ (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0);
+
+ free(fullBuf);
+
+ jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "<init>", "(I[B[B[B[BLjava/security/spec/ECParameterSpec;)V");
+ return (*env)->NewObject(env, pubkey_class, ec_pub_init, flag, meta_bytes, header_bytes, x_bytes, y_bytes, ec_pub_param_spec);
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) {
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE handle = NULL;
+
+ jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng");
+ jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring)(*env)->GetObjectField(env, self, type_id);
+ const char* type_data = (*env)->GetStringUTFChars(env, type, NULL);
+ LPCWSTR algo;
+ if (strcmp(type_data, "ECDH") == 0) {
+ switch (keysize) {
+ case 256:
+ algo = BCRYPT_ECDH_P256_ALGORITHM;
+ break;
+ case 384:
+ algo = BCRYPT_ECDH_P384_ALGORITHM;
+ break;
+ case 521:
+ algo = BCRYPT_ECDH_P521_ALGORITHM;
+ break;
+ default:
+ //unreachable
+ return NULL;
+ }
+ } else if (strcmp(type_data, "ECDSA") == 0) {
+ switch (keysize) {
+ case 256:
+ algo = BCRYPT_ECDSA_P256_ALGORITHM;
+ break;
+ case 384:
+ algo = BCRYPT_ECDSA_P384_ALGORITHM;
+ break;
+ case 521:
+ algo = BCRYPT_ECDSA_P521_ALGORITHM;
+ break;
+ default:
+ //unreachable
+ return NULL;
+ }
+ } else {
+ //unreachable
+ return NULL;
+ }
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, algo, MS_PRIMITIVE_PROVIDER, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider", status);
+ return NULL;
+ }
+
+ BCRYPT_KEY_HANDLE key = NULL;
+
+ if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, keysize, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGenerateKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return NULL;
+ }
+
+ if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptFinalizeKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return NULL;
+ }
+
+ jobject privkey = key_to_privkey(env, key, KEYFLAG_NIST, NULL);
+ jobject pubkey = key_to_pubkey(env, key, KEYFLAG_NIST, NULL);
+
+ jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "<init>", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+
+ BCryptDestroyKey(key);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey);
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random) {
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE handle = NULL;
+ BCRYPT_KEY_HANDLE key = NULL;
+
+ jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng");
+ jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring)(*env)->GetObjectField(env, self, type_id);
+ const char* type_data = (*env)->GetStringUTFChars(env, type, NULL);
+ LPCWSTR algo;
+ if (strcmp(type_data, "ECDH") == 0) {
+ algo = BCRYPT_ECDH_ALGORITHM;
+ } else if (strcmp(type_data, "ECDSA") == 0) {
+ algo = BCRYPT_ECDSA_ALGORITHM;
+ } else {
+ //unreachable
+ return NULL;
+ }
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+
+ jint keyflag;
+ NWPSTR curveName;
+ ULONG bits = init_algo(env, &handle, &keyflag, &curveName, algo, params);
+ if (bits == 0) {
+ throw_new(env, "java/security/GeneralSecurityException", "Couldn't initialize algo.");
+ return NULL;
+ }
+
+ if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, bits, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGenerateKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return NULL;
+ }
+
+ if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptFinalizeKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return NULL;
+ }
+
+ jobject privkey = key_to_privkey(env, key, keyflag, curveName);
+ jobject pubkey = key_to_pubkey(env, key, keyflag, curveName);
+
+ if (curveName) {
+ free(curveName);
+ }
+
+ jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "<init>", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+
+ BCryptDestroyKey(key);
+ BCryptCloseAlgorithmProvider(handle, 0);
+ return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey);
+}
+
+static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR type, jint keyflag, jbyteArray meta, jobject params) {
+ LPCWSTR ecdh_algos[] = {
+ BCRYPT_ECDH_ALGORITHM,
+ BCRYPT_ECDH_P256_ALGORITHM,
+ BCRYPT_ECDH_P384_ALGORITHM,
+ BCRYPT_ECDH_P521_ALGORITHM
+ };
+ LPCWSTR ecdsa_algos[] = {
+ BCRYPT_ECDSA_ALGORITHM,
+ BCRYPT_ECDSA_P256_ALGORITHM,
+ BCRYPT_ECDSA_P384_ALGORITHM,
+ BCRYPT_ECDSA_P521_ALGORITHM
+ };
+
+ LPCWSTR *algos;
+ LPCWSTR algo;
+ if (lstrcmpW(type, BCRYPT_ECDH_ALGORITHM) == 0) {
+ algos = ecdh_algos;
+ } else if (lstrcmpW(type, BCRYPT_ECDSA_ALGORITHM) == 0) {
+ algos = ecdsa_algos;
+ } else {
+ //unreachable
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (keyflag) {
+ case KEYFLAG_IMPLICIT:
+ case KEYFLAG_EXPLICIT:
+ case KEYFLAG_OTHER:
+ algo = algos[0];
+ break;
+ case KEYFLAG_NIST: {
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = (*env)->CallObjectMethod(env, params, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, elliptic_curve, get_field);
+
+ jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I");
+ jint bits = (*env)->CallIntMethod(env, field, get_bits);
+ switch (bits) {
+ case 256:
+ algo = algos[1];
+ break;
+ case 384:
+ algo = algos[2];
+ break;
+ case 521:
+ algo = algos[3];
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
+ }
+ NTSTATUS status;
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ return status;
+ }
+
+ switch (keyflag) {
+ case KEYFLAG_IMPLICIT: {
+ jint meta_len = (*env)->GetArrayLength(env, meta);
+ jbyte *meta_data = (*env)->GetByteArrayElements(env, meta, NULL);
+ //if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, meta_data, meta_len, 0))) {
+ // throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSetProperty(curve name)\n", status);
+ // (*env)->ReleaseByteArrayElements(env, meta, meta_data, JNI_ABORT);
+ // return status;
+ //}
+ (*env)->ReleaseByteArrayElements(env, meta, meta_data, JNI_ABORT);
+ break;
+ }
+ case KEYFLAG_EXPLICIT:
+ case KEYFLAG_OTHER: {
+ PBYTE curve;
+ ULONG curve_len = create_curve(env, params, &curve);
+ if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curve_len, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSetProperty(parameters)\n", status);
+ free(curve);
+ return status;
+ }
+ free(curve);
+ break;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+static jint get_keyflag(JNIEnv *env, jobject key) {
+ if ((*env)->IsInstanceOf(env, key, pubkey_class) || (*env)->IsInstanceOf(env, key, privkey_class)) {
+ jclass key_class = (*env)->GetObjectClass(env, key);
+ jmethodID get_flag = (*env)->GetMethodID(env, key_class, "getFlag", "()I");
+ return (*env)->CallIntMethod(env, key, get_flag);
+ } else {
+ return KEYFLAG_OTHER;
+ }
+}
+
+static jbyteArray get_meta(JNIEnv *env, jobject key) {
+ if ((*env)->IsInstanceOf(env, key, pubkey_class) || (*env)->IsInstanceOf(env, key, privkey_class)) {
+ jclass key_class = (*env)->GetObjectClass(env, key);
+ jmethodID get_meta = (*env)->GetMethodID(env, key_class, "getMeta", "()[B");
+ return (jbyteArray)(*env)->CallObjectMethod(env, key, get_meta);
+ } else {
+ return NULL;
+ }
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jobject pubkey, jobject privkey, jobject params) {
+ NTSTATUS status;
+
+ jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng");
+ jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring)(*env)->GetObjectField(env, self, type_id);
+ const char* type_data = (*env)->GetStringUTFChars(env, type, NULL);
+ LPCWSTR kdf_algo;
+ if (strcmp(type_data, "ECDHwithSHA1KDF") == 0) {
+ kdf_algo = BCRYPT_SHA1_ALGORITHM;
+ } else if (strcmp(type_data, "ECDHwithSHA256KDF") == 0) {
+ kdf_algo = BCRYPT_SHA256_ALGORITHM;
+ } else if (strcmp(type_data, "ECDHwithSHA384KDF") == 0) {
+ kdf_algo = BCRYPT_SHA384_ALGORITHM;
+ } else if (strcmp(type_data, "ECDHwithSHA512KDF") == 0) {
+ kdf_algo = BCRYPT_SHA512_ALGORITHM;
+ } else {
+ //unreachable
+ return NULL;
+ }
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+
+ BCRYPT_ALG_HANDLE kaHandle = NULL;
+
+ jint pub_flag = get_keyflag(env, pubkey);
+ if (pub_flag == KEYFLAG_OTHER) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native public key.");
+ return NULL;
+ }
+ jbyteArray meta = get_meta(env, pubkey);
+
+ if (NT_FAILURE(status = init_use_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, pub_flag, meta, params))) {
+ return NULL;
+ }
+
+ BCRYPT_KEY_HANDLE pkey = NULL;
+ BCRYPT_KEY_HANDLE skey = NULL;
+
+ jmethodID get_data_priv = (*env)->GetMethodID(env, pubkey_class, "getData", "()[B");
+ jbyteArray pubkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, pubkey, get_data_priv);
+
+ jint pub_length = (*env)->GetArrayLength(env, pubkey_barray);
+ jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey_barray, NULL);
+ if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair(pub)\n", status);
+ BCryptCloseAlgorithmProvider(kaHandle, 0);
+ (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT);
+
+ jint priv_flag = get_keyflag(env, privkey);
+ if (priv_flag == KEYFLAG_OTHER) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native private key.");
+ return NULL;
+ }
+
+ jmethodID get_data_pub = (*env)->GetMethodID(env, privkey_class, "getData", "()[B");
+ jbyteArray privkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, privkey, get_data_pub);
+
+ jint priv_length = (*env)->GetArrayLength(env, privkey_barray);
+ jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey_barray, NULL);
+ if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair(priv)\n", status);
+ BCryptCloseAlgorithmProvider(kaHandle, 0);
+ BCryptDestroyKey(pkey);
+ (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT);
+
+ BCRYPT_SECRET_HANDLE ka = NULL;
+
+ if (NT_FAILURE(status = BCryptSecretAgreement(skey, pkey, &ka, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSecretAgreement\n", status);
+ BCryptCloseAlgorithmProvider(kaHandle, 0);
+ BCryptDestroyKey(pkey);
+ BCryptDestroyKey(skey);
+ return NULL;
+ }
+
+ BCryptBufferDesc paramList = { 0 };
+ BCryptBuffer kdfParams[1] = { 0 };
+ kdfParams[0].BufferType = KDF_HASH_ALGORITHM;
+ kdfParams[0].cbBuffer = (DWORD)((wcslen(kdf_algo) + 1) * sizeof(WCHAR));
+ kdfParams[0].pvBuffer = (PVOID)kdf_algo;
+ paramList.cBuffers = 1;
+ paramList.pBuffers = kdfParams;
+ paramList.ulVersion = BCRYPTBUFFER_VERSION;
+
+ //TODO: Is this the actual KDF-1 or KDF-2 algo or something completely different? *This does not use the counter!!!*
+ ULONG bufSize = 0;
+ if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, &paramList, NULL, 0, &bufSize, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptDeriveKey(length only)\n", status);
+ return NULL;
+ }
+
+ PBYTE derived = calloc(bufSize, 1);
+ if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, &paramList, derived, bufSize, &bufSize, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptDeriveKey(whole)\n", status);
+ return NULL;
+ }
+
+ jbyteArray result = (*env)->NewByteArray(env, bufSize);
+ jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL);
+ memcpy(result_data, derived, bufSize);
+ (*env)->ReleaseByteArrayElements(env, result, result_data, 0);
+
+ free(derived);
+ BCryptDestroyKey(pkey);
+ BCryptDestroyKey(skey);
+ BCryptDestroySecret(ka);
+ BCryptCloseAlgorithmProvider(kaHandle, 0);
+ return result;
+}
+
+static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) {
+ jclass mscng_sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Mscng");
+ jfieldID type_id = (*env)->GetFieldID(env, mscng_sig_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring)(*env)->GetObjectField(env, self, type_id);
+ const char* type_data = (*env)->GetStringUTFChars(env, type, NULL);
+ LPCWSTR hash_algo;
+ if (strcmp(type_data, "SHA1withECDSA") == 0) {
+ hash_algo = BCRYPT_SHA1_ALGORITHM;
+ } else if (strcmp(type_data, "SHA256withECDSA") == 0) {
+ hash_algo = BCRYPT_SHA256_ALGORITHM;
+ } else if (strcmp(type_data, "SHA384withECDSA") == 0) {
+ hash_algo = BCRYPT_SHA384_ALGORITHM;
+ } else if (strcmp(type_data, "SHA512withECDSA") == 0) {
+ hash_algo = BCRYPT_SHA512_ALGORITHM;
+ } else {
+ //unreachable
+ return NULL;
+ }
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+ return hash_algo;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jobject privkey, jobject params) {
+ NTSTATUS status;
+ LPCWSTR hash_algo = get_sighash_algo(env, self);
+
+ BCRYPT_ALG_HANDLE sigHandle = NULL;
+
+ jint keyflag = get_keyflag(env, privkey);
+ if (keyflag == KEYFLAG_OTHER) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native private key.");
+ return NULL;
+ }
+ jbyteArray meta = get_meta(env, privkey);
+
+ if (NT_FAILURE(status = init_use_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, keyflag, meta, params))) {
+ return NULL;
+ }
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&sigHandle, BCRYPT_ECDSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ return NULL;
+ }
+
+ BCRYPT_ALG_HANDLE hashHandle = NULL;
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ return NULL;
+ }
+
+ DWORD dummy = 0;
+ DWORD hash_len = 0;
+ if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGetProperty(hash len)\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ return NULL;
+ }
+
+ PBYTE hash = calloc(hash_len, 1);
+
+ jint data_len = (*env)->GetArrayLength(env, data);
+ jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL);
+ if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptHash\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+
+ BCRYPT_KEY_HANDLE skey = NULL;
+
+ jmethodID get_data = (*env)->GetMethodID(env, privkey_class, "getData", "()[B");
+ jbyteArray privkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, privkey, get_data);
+
+
+ jint priv_length = (*env)->GetArrayLength(env, privkey_barray);
+ jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey_barray, NULL);
+ if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT);
+
+ DWORD sig_len = 0;
+ if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSignHash(len only)\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ return NULL;
+ }
+
+ jbyteArray sig = (*env)->NewByteArray(env, sig_len);
+ jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL);
+ if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSignHash(do)\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0);
+
+ free(hash);
+
+ BCryptDestroyKey(skey);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+
+ return sig;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jobject pubkey, jobject params) {
+ NTSTATUS status;
+ LPCWSTR hash_algo = get_sighash_algo(env, self);
+
+ BCRYPT_ALG_HANDLE sigHandle = NULL;
+
+ jint keyflag = get_keyflag(env, pubkey);
+ if (keyflag == KEYFLAG_OTHER) { // TODO: This is not necessary
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native public key.");
+ return JNI_FALSE;
+ }
+ jbyteArray meta = get_meta(env, pubkey);
+
+ if (NT_FAILURE(status = init_use_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, keyflag, meta, params))) {
+ return JNI_FALSE;
+ }
+
+ BCRYPT_ALG_HANDLE hashHandle = NULL;
+
+ if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ return JNI_FALSE;
+ }
+
+ DWORD dummy = 0;
+ DWORD hash_len = 0;
+ if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGetProperty(hash len)\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ return JNI_FALSE;
+ }
+
+ PBYTE hash = calloc(hash_len, 1);
+
+ jint data_len = (*env)->GetArrayLength(env, data);
+ jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL);
+ if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptHash\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+ return JNI_FALSE;
+ }
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+
+ BCRYPT_KEY_HANDLE pkey = NULL;
+
+ jmethodID get_data = (*env)->GetMethodID(env, pubkey_class, "getData", "()[B");
+ jbyteArray pubkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, pubkey, get_data);
+
+
+ jint pub_length = (*env)->GetArrayLength(env, pubkey_barray);
+ jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey_barray, NULL);
+ if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair\n", status);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT);
+ return JNI_FALSE;
+ }
+ (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT);
+
+ jint sig_len = (*env)->GetArrayLength(env, sig);
+ jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL);
+ NTSTATUS result = BCryptVerifySignature(pkey, NULL, hash, hash_len, sig_data, sig_len, 0);
+ (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT);
+
+ free(hash);
+
+ BCryptDestroyKey(pkey);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+
+ if (result == STATUS_SUCCESS) {
+ return JNI_TRUE;
+ } else if (result == STATUS_INVALID_SIGNATURE) {
+ return JNI_FALSE;
+ } else {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptVerifySignature\n", status);
+ return JNI_FALSE;
+ }
+} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h
index d714b39..dcdaa1b 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -1,344 +1,857 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class cz_crcs_ectester_standalone_libs_TomcryptLib */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_TomcryptLib
-#define _Included_cz_crcs_ectester_standalone_libs_TomcryptLib
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
- * Method: createProvider
- * Signature: ()Ljava/security/Provider;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_createProvider
- (JNIEnv *, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
- * Method: getCurves
- * Signature: ()Ljava/util/Set;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves
- (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392LL
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE 2147483639L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS 0L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES 1L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES 2L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840LL
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739LL
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
- * Method: setup
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024TomCrypt_setup
- (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
- * Method: keysizeSupported
- * Signature: (I)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
- * Method: paramsSupported
- * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_paramsSupported
- (JNIEnv *, jobject, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
- * Method: generate
- * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__ILjava_security_SecureRandom_2
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
- * Method: generate
- * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2
- (JNIEnv *, jobject, jobject, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
- * Method: generateSecret
- * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
- */
-JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
- * Method: sign
- * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
- */
-JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
- * Method: verify
- * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_BotanLib */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_BotanLib
-#define _Included_cz_crcs_ectester_standalone_libs_BotanLib
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_BotanLib
- * Method: createProvider
- * Signature: ()Ljava/security/Provider;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider
- (JNIEnv *, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_BotanLib
- * Method: getCurves
- * Signature: ()Ljava/util/Set;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves
- (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 1421746759512286392LL
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE 2147483639L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS 0L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES 1L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES 2L
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 4112578634029874840LL
-#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
-#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -4298000515446427739LL
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
- * Method: setup
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Botan_setup
- (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
- * Method: keysizeSupported
- * Signature: (I)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
- * Method: paramsSupported
- * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_paramsSupported
- (JNIEnv *, jobject, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
- * Method: generate
- * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__ILjava_security_SecureRandom_2
- (JNIEnv *, jobject, jint, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
- * Method: generate
- * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
- */
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2
- (JNIEnv *, jobject, jobject, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
- * Method: generateSecret
- * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
- */
-JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Botan_generateSecret
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan */
-
-#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
-#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
- * Method: sign
- * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
- */
-JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_sign
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
-
-/*
- * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
- * Method: verify
- * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
- */
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_verify
- (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class cz_crcs_ectester_standalone_libs_TomcryptLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_TomcryptLib
+#define _Included_cz_crcs_ectester_standalone_libs_TomcryptLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739i64
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024TomCrypt_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2
+ (JNIEnv *, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_BotanLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_BotanLib
+#define _Included_cz_crcs_ectester_standalone_libs_BotanLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 1421746759512286392i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -4298000515446427739i64
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Botan_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2
+ (JNIEnv *, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Botan_generateSecret
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_CryptoppLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_CryptoppLib
+#define _Included_cz_crcs_ectester_standalone_libs_CryptoppLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 1421746759512286392i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -4298000515446427739i64
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Cryptopp_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2
+ (JNIEnv *, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Cryptopp_generateSecret
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_OpensslLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_OpensslLib
+#define _Included_cz_crcs_ectester_standalone_libs_OpensslLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 1421746759512286392i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -4298000515446427739i64
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Openssl_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2
+ (JNIEnv *, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Openssl_generateSecret
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_MscngLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_MscngLib
+#define _Included_cz_crcs_ectester_standalone_libs_MscngLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MscngLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MscngLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 1421746759512286392i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 4112578634029874840i64
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -4298000515446427739i64
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2
+ (JNIEnv *, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng
+ * Method: generateSecret
+ * Signature: (Ljava/security/interfaces/ECPublicKey;Ljava/security/interfaces/ECPrivateKey;Ljava/security/spec/AlgorithmParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret
+ (JNIEnv *, jobject, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng
+ * Method: sign
+ * Signature: ([BLjava/security/interfaces/ECPrivateKey;Ljava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign
+ (JNIEnv *, jobject, jbyteArray, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng
+ * Method: verify
+ * Signature: ([B[BLjava/security/interfaces/ECPublicKey;Ljava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
new file mode 100644
index 0000000..259630c
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
@@ -0,0 +1,567 @@
+#include "native.h"
+#include <string.h>
+#include <stdio.h>
+
+#include <openssl/conf.h>
+#include <openssl/opensslv.h>
+#include <openssl/objects.h>
+#include <openssl/obj_mac.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+
+#include "c_utils.h"
+
+
+static jclass provider_class;
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_createProvider(JNIEnv *env, jobject self) {
+ /* Create the custom provider. */
+ jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Openssl");
+ provider_class = (*env)->NewGlobalRef(env, local_provider_class);
+
+ jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V");
+
+ jstring name = (*env)->NewStringUTF(env, OPENSSL_VERSION_TEXT);
+ long ver_hi = (OPENSSL_VERSION_NUMBER & 0xff000000L) >> 28;
+ long ver_mid = (OPENSSL_VERSION_NUMBER & 0xff0000L) >> 20;
+ long ver_low = (OPENSSL_VERSION_NUMBER & 0xff00L) >> 12;
+ double version = (double)ver_hi + ((double)ver_mid/10) + ((double)ver_low/100);
+
+ return (*env)->NewObject(env, provider_class, init, name, version, name);
+}
+
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Openssl_setup(JNIEnv *env, jobject self) {
+ OPENSSL_no_config();
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+
+ INIT_PROVIDER(env, provider_class);
+
+ ADD_KPG(env, self, "EC", "Openssl");
+ ADD_KA(env, self, "ECDH", "OpensslECDH");
+ ADD_SIG(env, self, "NONEwithECDSA", "OpensslECDSAwithNONE");
+
+ init_classes(env, "Openssl");
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves(JNIEnv *env, jobject self) {
+ jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet");
+
+ jmethodID hash_set_ctr = (*env)->GetMethodID(env, hash_set_class, "<init>", "()V");
+ jmethodID hash_set_add = (*env)->GetMethodID(env, hash_set_class, "add", "(Ljava/lang/Object;)Z");
+
+ jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr);
+
+ size_t ncurves = EC_get_builtin_curves(NULL, 0);
+ EC_builtin_curve curves[ncurves];
+ EC_get_builtin_curves(curves, ncurves);
+
+ for (size_t i = 0; i < ncurves; ++i) {
+ jstring curve_name = (*env)->NewStringUTF(env, OBJ_nid2sn(curves[i].nid));
+ (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name);
+ }
+
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_keysizeSupported(JNIEnv *env, jobject self, jint keysize) {
+ size_t ncurves = EC_get_builtin_curves(NULL, 0);
+ EC_builtin_curve curves[ncurves];
+ EC_get_builtin_curves(curves, ncurves);
+
+ for (size_t i = 0; i < ncurves; ++i) {
+ EC_GROUP *curve = EC_GROUP_new_by_curve_name(curves[i].nid);
+ if (EC_GROUP_get_degree(curve) == keysize) {
+ EC_GROUP_clear_free(curve);
+ return JNI_TRUE;
+ }
+ EC_GROUP_free(curve);
+ }
+ return JNI_FALSE;
+}
+
+static jobject bignum_to_biginteger(JNIEnv *env, const BIGNUM *bn) {
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "<init>", "(I[B)V");
+ int size = BN_num_bytes(bn);
+ jbyteArray bytes = (*env)->NewByteArray(env, size);
+ jbyte *data = (*env)->GetByteArrayElements(env, bytes, NULL);
+ BN_bn2bin(bn, data);
+ (*env)->ReleaseByteArrayElements(env, bytes, data, 0);
+ jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, bytes);
+ return result;
+}
+
+static BIGNUM *biginteger_to_bignum(JNIEnv *env, jobject bigint) {
+ jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
+
+ jbyteArray byte_array = (jbyteArray) (*env)->CallObjectMethod(env, bigint, to_byte_array);
+ jsize byte_length = (*env)->GetArrayLength(env, byte_array);
+ jbyte *byte_data = (*env)->GetByteArrayElements(env, byte_array, NULL);
+ BIGNUM *result = BN_bin2bn(byte_data, byte_length, NULL);
+ (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT);
+ return result;
+}
+
+static EC_GROUP *create_curve(JNIEnv *env, jobject params) {
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = (*env)->CallObjectMethod(env, params, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, elliptic_curve, get_field);
+
+ jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I");
+ jint bits = (*env)->CallIntMethod(env, field, get_bits);
+ jint bytes = (bits + 7) / 8;
+
+ jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a);
+ BIGNUM *a_bn = biginteger_to_bignum(env, a);
+
+ jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b);
+ BIGNUM *b_bn = biginteger_to_bignum(env, b);
+
+ jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g = (*env)->CallObjectMethod(env, params, get_g);
+
+ jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = (*env)->CallObjectMethod(env, g, get_x);
+ BIGNUM *gx_bn = biginteger_to_bignum(env, gx);
+
+ jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = (*env)->CallObjectMethod(env, g, get_y);
+ BIGNUM *gy_bn = biginteger_to_bignum(env, gy);
+
+ EC_GROUP *result;
+ EC_POINT *g_point;
+
+ if ((*env)->IsInstanceOf(env, field, fp_field_class)) {
+ jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;");
+ jobject p = (*env)->CallObjectMethod(env, field, get_p);
+
+ BIGNUM *p_bn = biginteger_to_bignum(env, p);
+ result = EC_GROUP_new_curve_GFp(p_bn, a_bn, b_bn, NULL);
+ BN_free(p_bn);
+ if (!result) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_new_curve_GFp.");
+ BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn);
+ return NULL;
+ }
+
+ g_point = EC_POINT_new(result);
+ if(!EC_POINT_set_affine_coordinates_GFp(result, g_point, gx_bn, gy_bn, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_POINT_set_affine_coordinates_GFp.");
+ BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result);
+ return NULL;
+ }
+ } else if ((*env)->IsInstanceOf(env, field, f2m_field_class)) {
+ jmethodID get_reduction_poly = (*env)->GetMethodID(env, f2m_field_class, "getReductionPolynomial", "()Ljava/math/BigInteger;");
+ jobject red_poly = (*env)->CallObjectMethod(env, field, get_reduction_poly);
+
+ BIGNUM *p_bn = biginteger_to_bignum(env, red_poly);
+ result = EC_GROUP_new_curve_GF2m(p_bn, a_bn, b_bn, NULL);
+ BN_free(p_bn);
+ if (!result) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_new_curve_GF2m.");
+ BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn);
+ return NULL;
+ }
+
+ g_point = EC_POINT_new(result);
+ if(!EC_POINT_set_affine_coordinates_GF2m(result, g_point, gx_bn, gy_bn, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_POINT_set_affine_coordinates_GF2m.");
+ BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+
+ BN_free(a_bn);
+ BN_free(b_bn);
+
+ jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject n = (*env)->CallObjectMethod(env, params, get_n);
+ BIGNUM *n_bn = biginteger_to_bignum(env, n);
+
+ jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I");
+ jint h = (*env)->CallIntMethod(env, params, get_h);
+ BIGNUM *h_bn = BN_new();
+ BN_set_word(h_bn, h);
+
+ if (!EC_GROUP_set_generator(result, g_point, n_bn, h_bn)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_set_generator.");
+ BN_free(n_bn); BN_free(h_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result);
+ return NULL;
+ }
+
+ EC_POINT_free(g_point);
+ BN_free(gx_bn);
+ BN_free(gy_bn);
+ BN_free(n_bn);
+ BN_free(h_bn);
+
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_paramsSupported(JNIEnv *env, jobject self, jobject params){
+ if (params == NULL) {
+ return JNI_FALSE;
+ }
+
+ if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ EC_GROUP *curve = create_curve(env, params);
+ jboolean result = (EC_GROUP_check(curve, NULL) == 1) ? JNI_TRUE : JNI_FALSE;
+ EC_GROUP_free(curve);
+ return result;
+ } else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (*env)->CallObjectMethod(env, params, get_name);
+ const char *utf_name = (*env)->GetStringUTFChars(env, name, NULL);
+ size_t ncurves = EC_get_builtin_curves(NULL, 0);
+ EC_builtin_curve curves[ncurves];
+ EC_get_builtin_curves(curves, ncurves);
+ for (size_t i = 0; i < ncurves; ++i) {
+ if (strcasecmp(utf_name, OBJ_nid2sn(curves[i].nid)) == 0) {
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ return JNI_TRUE;
+ }
+ }
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ return JNI_FALSE;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) {
+ int field_type = EC_METHOD_get_field_type(EC_GROUP_method_of(curve));
+ BIGNUM *a;
+ BIGNUM *b;
+
+ BIGNUM *gx;
+ BIGNUM *gy;
+ jobject field;
+
+ if (field_type == NID_X9_62_prime_field) {
+ BIGNUM *p = BN_new();
+ a = BN_new();
+ b = BN_new();
+ if (!EC_GROUP_get_curve_GFp(curve, p, a, b, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_curve_GFp.");
+ BN_free(p); BN_free(a); BN_free(b);
+ return NULL;
+ }
+
+ jobject p_int = bignum_to_biginteger(env, p);
+
+ jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "<init>", "(Ljava/math/BigInteger;)V");
+ field = (*env)->NewObject(env, fp_field_class, fp_field_init, p_int);
+
+ BN_free(p);
+
+ gx = BN_new();
+ gy = BN_new();
+ if (!EC_POINT_get_affine_coordinates_GFp(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_POINT_get_affine_coordinates_GFp.");
+ BN_free(a); BN_free(b); BN_free(gx); BN_free(gy);
+ return NULL;
+ }
+
+ } else if (field_type == NID_X9_62_characteristic_two_field) {
+ a = BN_new();
+ b = BN_new();
+ if (!EC_GROUP_get_curve_GF2m(curve, NULL, a, b, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_curve_GF2m.");
+ BN_free(a); BN_free(b);
+ return NULL;
+ }
+
+ int basis_type = EC_GROUP_get_basis_type(curve);
+ jintArray ks;
+ jint *ks_data;
+ if (basis_type == NID_X9_62_tpBasis) {
+ ks = (*env)->NewIntArray(env, 1);
+ ks_data = (*env)->GetIntArrayElements(env, ks, NULL);
+ if (!EC_GROUP_get_trinomial_basis(curve, &ks_data[0])) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_trinomial_basis.");
+ BN_free(a); BN_free(b);
+ (*env)->ReleaseIntArrayElements(env, ks, ks_data, JNI_ABORT);
+ return NULL;
+ }
+ } else if (basis_type == NID_X9_62_ppBasis) {
+ ks = (*env)->NewIntArray(env, 3);
+ ks_data = (*env)->GetIntArrayElements(env, ks, NULL);
+ if (!EC_GROUP_get_pentanomial_basis(curve, &ks_data[0], &ks_data[1], &ks_data[2])) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_pentanomial_basis.");
+ BN_free(a); BN_free(b);
+ (*env)->ReleaseIntArrayElements(env, ks, ks_data, JNI_ABORT);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+ (*env)->ReleaseIntArrayElements(env, ks, ks_data, 0);
+
+ jint m = EC_GROUP_get_degree(curve);
+
+ jmethodID f2m_field_init = (*env)->GetMethodID(env, f2m_field_class, "<init>", "(I[I)V");
+ field = (*env)->NewObject(env, f2m_field_class, f2m_field_init, m, ks);
+
+ gx = BN_new();
+ gy = BN_new();
+ if (!EC_POINT_get_affine_coordinates_GF2m(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL)) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_POINT_get_affine_coordinates_GF2m.");
+ BN_free(a); BN_free(b); BN_free(gx); BN_free(gy);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+
+ jobject a_int = bignum_to_biginteger(env, a);
+ jobject b_int = bignum_to_biginteger(env, b);
+
+ jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "<init>", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject elliptic_curve = (*env)->NewObject(env, elliptic_curve_class, elliptic_curve_init, field, a_int, b_int);
+ fflush(stderr);
+
+ BN_free(a);
+ BN_free(b);
+
+ jobject gx_int = bignum_to_biginteger(env, gx);
+ jobject gy_int = bignum_to_biginteger(env, gy);
+
+ BN_free(gx);
+ BN_free(gy);
+
+ jmethodID point_init = (*env)->GetMethodID(env, point_class, "<init>", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int);
+
+ jobject order = bignum_to_biginteger(env, EC_GROUP_get0_order(curve));
+ jint cofactor = BN_get_word(EC_GROUP_get0_cofactor(curve));
+
+ jmethodID ec_parameter_spec_init = (*env)->GetMethodID(env, ec_parameter_spec_class, "<init>", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V");
+ return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, order, cofactor);
+}
+
+static jobject generate_from_curve(JNIEnv *env, const EC_GROUP *curve) {
+ jint keysize = EC_GROUP_get_degree(curve);
+ unsigned long key_bytes = (keysize + 7) / 8;
+
+ EC_KEY *key = EC_KEY_new();
+ EC_KEY_set_group(key, curve);
+ if (!EC_KEY_generate_key(key)) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error generating key, EC_KEY_generate_key.");
+ EC_KEY_free(key);
+ return NULL;
+ }
+
+ jbyteArray priv_bytes = (*env)->NewByteArray(env, key_bytes);
+ jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
+ BN_bn2binpad(EC_KEY_get0_private_key(key), key_priv, key_bytes);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
+
+ unsigned long key_len = 2*key_bytes + 1;
+ jbyteArray pub_bytes = (*env)->NewByteArray(env, key_len);
+ jbyte *key_pub = (*env)->GetByteArrayElements(env, pub_bytes, NULL);
+ EC_POINT_point2oct(curve, EC_KEY_get0_public_key(key), POINT_CONVERSION_UNCOMPRESSED, key_pub, key_len, NULL);
+ (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, 0);
+
+ EC_KEY_free(key);
+
+ jobject ec_param_spec = create_ec_param_spec(env, curve);
+
+ jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
+ jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject pubkey = (*env)->NewObject(env, pubkey_class, ec_pub_init, pub_bytes, ec_param_spec);
+
+ jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
+ jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject privkey = (*env)->NewObject(env, privkey_class, ec_priv_init, priv_bytes, ec_priv_param_spec);
+
+ jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "<init>", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+ return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey);
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) {
+ size_t ncurves = EC_get_builtin_curves(NULL, 0);
+ EC_builtin_curve curves[ncurves];
+ EC_get_builtin_curves(curves, ncurves);
+
+ EC_GROUP *curve = NULL;
+ for (size_t i = 0; i < ncurves; ++i) {
+ curve = EC_GROUP_new_by_curve_name(curves[i].nid);
+ if (EC_GROUP_get_degree(curve) == keysize) {
+ break;
+ }
+ EC_GROUP_free(curve);
+ }
+
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve for given bitsize not found.");
+ return NULL;
+ }
+
+ jobject result = generate_from_curve(env, curve);
+ EC_GROUP_free(curve);
+ return result;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random) {
+ if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ EC_GROUP *curve = create_curve(env, params);
+ jobject result = generate_from_curve(env, curve);
+ EC_GROUP_free(curve);
+ return result;
+ } else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (*env)->CallObjectMethod(env, params, get_name);
+ const char* utf_name = (*env)->GetStringUTFChars(env, name, NULL);
+ size_t ncurves = EC_get_builtin_curves(NULL, 0);
+ EC_builtin_curve curves[ncurves];
+ EC_get_builtin_curves(curves, ncurves);
+ EC_GROUP *curve;
+ for (size_t i = 0; i < ncurves; ++i) {
+ if (strcasecmp(utf_name, OBJ_nid2sn(curves[i].nid)) == 0) {
+ curve = EC_GROUP_new_by_curve_name(curves[i].nid);
+ break;
+ }
+ }
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve for given bitsize not found.");
+ return NULL;
+ }
+ jobject result = generate_from_curve(env, curve);
+ EC_GROUP_free(curve);
+ return result;
+ } else {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found.");
+ return NULL;
+ }
+}
+
+EC_KEY *barray_to_pubkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray pub) {
+ EC_KEY *result = EC_KEY_new();
+ EC_KEY_set_group(result, curve);
+ jsize pub_len = (*env)->GetArrayLength(env, pub);
+ jbyte *pub_data = (*env)->GetByteArrayElements(env, pub, NULL);
+ EC_POINT *pub_point = EC_POINT_new(curve);
+ EC_POINT_oct2point(curve, pub_point, pub_data, pub_len, NULL);
+ (*env)->ReleaseByteArrayElements(env, pub, pub_data, JNI_ABORT);
+ EC_KEY_set_public_key(result, pub_point);
+ EC_POINT_free(pub_point);
+ return result;
+}
+
+EC_KEY *barray_to_privkey(JNIEnv *env, const EC_GROUP *curve, jbyteArray priv) {
+ EC_KEY *result = EC_KEY_new();
+ EC_KEY_set_group(result, curve);
+ jsize priv_len = (*env)->GetArrayLength(env, priv);
+ jbyte *priv_data = (*env)->GetByteArrayElements(env, priv, NULL);
+ BIGNUM *s = BN_bin2bn(priv_data, priv_len, NULL);
+ (*env)->ReleaseByteArrayElements(env, priv, priv_data, JNI_ABORT);
+ EC_KEY_set_private_key(result, s);
+ BN_free(s);
+ return result;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Openssl_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) {
+ EC_GROUP *curve = create_curve(env, params);
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found.");
+ return NULL;
+ }
+
+ EC_KEY *pub = barray_to_pubkey(env, curve, pubkey);
+ EC_KEY *priv = barray_to_privkey(env, curve, privkey);
+
+ int field_size = EC_GROUP_get_degree(curve);
+ size_t secret_len = (field_size + 7)/8;
+
+ //TODO: Do more KeyAgreements here, but will have to do the hash-fun manually,
+ // probably using the ECDH_KDF_X9_62 by wrapping it and dynamically choosing the EVP_MD. from the type string.
+ jbyteArray result = (*env)->NewByteArray(env, secret_len);
+ jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL);
+ if (ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL) <= 0) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key.");
+ EC_KEY_free(pub); EC_KEY_free(priv); EC_GROUP_free(curve);
+ (*env)->ReleaseByteArrayElements(env, result, result_data, JNI_ABORT);
+ return NULL;
+ }
+ (*env)->ReleaseByteArrayElements(env, result, result_data, 0);
+
+ EC_KEY_free(pub);
+ EC_KEY_free(priv);
+ EC_GROUP_free(curve);
+ return result;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) {
+ EC_GROUP *curve = create_curve(env, params);
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found.");
+ return NULL;
+ }
+
+ EC_KEY *priv = barray_to_privkey(env, curve, privkey);
+
+ jsize data_size = (*env)->GetArrayLength(env, data);
+ jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+ // TODO: Do more Signatures here, maybe use the EVP interface to get to the hashes easier and not hash manually?
+ ECDSA_SIG *signature = ECDSA_do_sign(data_data, data_size, priv);
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ if (!signature) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error signing, ECDSA_do_sign.");
+ EC_KEY_free(priv); EC_GROUP_free(curve);
+ return NULL;
+ }
+
+ jsize sig_len = i2d_ECDSA_SIG(signature, NULL);
+ jbyteArray result = (*env)->NewByteArray(env, sig_len);
+ jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL);
+ jbyte *result_data_ptr = result_data;
+ i2d_ECDSA_SIG(signature, (unsigned char **)&result_data_ptr);
+ (*env)->ReleaseByteArrayElements(env, result, result_data, 0);
+
+ ECDSA_SIG_free(signature);
+ EC_KEY_free(priv);
+ EC_GROUP_free(curve);
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_verify(JNIEnv *env, jobject self, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params) {
+ EC_GROUP *curve = create_curve(env, params);
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found.");
+ return JNI_FALSE;
+ }
+
+ EC_KEY *pub = barray_to_pubkey(env, curve, pubkey);
+
+ jsize sig_len = (*env)->GetArrayLength(env, signature);
+ jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL);
+ jbyte *sig_data_ptr = sig_data;
+ ECDSA_SIG *sig_obj = d2i_ECDSA_SIG(NULL, (const unsigned char **)&sig_data_ptr, sig_len);
+ (*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
+
+ jsize data_size = (*env)->GetArrayLength(env, data);
+ jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+ int result = ECDSA_do_verify(data_data, data_size, sig_obj, pub);
+ if (result < 0) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error verifying, ECDSA_do_verify.");
+ EC_KEY_free(pub); EC_GROUP_free(curve); ECDSA_SIG_free(sig_obj);
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ return JNI_FALSE;
+ }
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+
+ ECDSA_SIG_free(sig_obj);
+ EC_KEY_free(pub);
+ EC_GROUP_free(curve);
+ return (result == 1) ? JNI_TRUE : JNI_FALSE;
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
index 29ee707..d609a48 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
@@ -128,6 +128,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa
}
curve++;
}
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
return JNI_FALSE;
} else {
return JNI_FALSE;
@@ -229,6 +230,17 @@ static ltc_ecc_set_type* create_curve(JNIEnv *env, jobject params) {
return curve;
}
+static void free_curve(ltc_ecc_set_type *curve) {
+ if (curve) {
+ free((void*)curve->prime);
+ free((void*)curve->B);
+ free((void*)curve->order);
+ free((void*)curve->Gx);
+ free((void*)curve->Gy);
+ free(curve);
+ }
+}
+
static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
ecc_key key;
int err;
@@ -240,7 +252,7 @@ static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
jbyteArray pub_bytes = (*env)->NewByteArray(env, key_len);
jbyte *key_pub = (*env)->GetByteArrayElements(env, pub_bytes, NULL);
ecc_ansi_x963_export(&key, key_pub, &key_len);
- (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, JNI_COMMIT);
+ (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, 0);
jobject ec_param_spec = create_ec_param_spec(env, curve);
@@ -251,7 +263,7 @@ static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
jbyteArray priv_bytes = (*env)->NewByteArray(env, curve->size);
jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
ltc_mp.unsigned_write(key.k, key_priv);
- (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, JNI_COMMIT);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
@@ -286,7 +298,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai
if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
ltc_ecc_set_type *curve = create_curve(env, params);
jobject result = generate_from_curve(env, curve);
- free(curve);
+ free_curve(curve);
return result;
} else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) {
jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
@@ -356,13 +368,13 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
ecc_key pub;
if (!pubkey_from_bytes(env, pubkey, curve, &pub)) {
- free(curve);
+ free_curve(curve);
return NULL;
}
ecc_key priv;
if (!privkey_from_bytes(env, privkey, curve, &priv)) {
- free(curve);
+ free_curve(curve);
return NULL;
}
@@ -371,17 +383,17 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
int err;
if ((err = ecc_shared_secret(&priv, &pub, result, &output_len)) != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
- free(curve);
+ free_curve(curve);
return NULL;
}
jbyteArray output = (*env)->NewByteArray(env, curve->size);
jbyte *output_data = (*env)->GetByteArrayElements(env, output, NULL);
memcpy(output_data, result, curve->size);
- (*env)->ReleaseByteArrayElements(env, output, output_data, JNI_COMMIT);
+ (*env)->ReleaseByteArrayElements(env, output, output_data, 0);
ltc_cleanup_multi(&pub.pubkey.x, &pub.pubkey.y, &pub.pubkey.z, &priv.k, NULL);
- free(curve);
+ free_curve(curve);
return output;
}
@@ -390,7 +402,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
ecc_key priv;
if (!privkey_from_bytes(env, privkey, curve, &priv)) {
- free(curve);
+ free_curve(curve);
return NULL;
}
@@ -402,7 +414,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
int err;
if ((err = ecc_sign_hash(data_data, data_size, result, &output_len, &ltc_prng, find_prng("yarrow"), &priv)) != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
- free(curve);
+ free_curve(curve);
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
return NULL;
}
@@ -412,9 +424,9 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jbyteArray output = (*env)->NewByteArray(env, output_len);
jbyte *output_data = (*env)->GetByteArrayElements(env, output, NULL);
memcpy(output_data, result, output_len);
- (*env)->ReleaseByteArrayElements(env, output, output_data, JNI_COMMIT);
+ (*env)->ReleaseByteArrayElements(env, output, output_data, 0);
- free(curve);
+ free_curve(curve);
return output;
}
@@ -423,7 +435,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
ecc_key pub;
if (!pubkey_from_bytes(env, pubkey, curve, &pub)) {
- free(curve);
+ free_curve(curve);
return JNI_FALSE;
}
@@ -437,7 +449,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
int result;
if ((err = ecc_verify_hash(sig_data, sig_size, data_data, data_size, &result, &pub)) != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
- free(curve);
+ free_curve(curve);
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
return JNI_FALSE;
@@ -445,6 +457,6 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
- free(curve);
+ free_curve(curve);
return result;
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/output/TextTestWriter.java b/src/cz/crcs/ectester/standalone/output/TextTestWriter.java
index 972af18..bf9ec7d 100644
--- a/src/cz/crcs/ectester/standalone/output/TextTestWriter.java
+++ b/src/cz/crcs/ectester/standalone/output/TextTestWriter.java
@@ -1,8 +1,12 @@
package cz.crcs.ectester.standalone.output;
+import cz.crcs.ectester.common.cli.Colors;
import cz.crcs.ectester.common.output.BaseTextTestWriter;
import cz.crcs.ectester.common.test.TestSuite;
import cz.crcs.ectester.common.test.Testable;
+import cz.crcs.ectester.standalone.ECTesterStandalone;
+import cz.crcs.ectester.standalone.test.base.StandaloneTestable;
+import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
import java.io.PrintStream;
@@ -14,15 +18,38 @@ public class TextTestWriter extends BaseTextTestWriter {
super(output);
}
+ private String causeString(Object cause) {
+ if (cause == null) {
+ return "";
+ } else if (cause instanceof Exception) {
+ Exception ex = ((Exception) cause);
+ return " -> " + ex.getClass().getCanonicalName() + " : " + ex.getMessage();
+ } else {
+ return cause.toString();
+ }
+ }
+
@Override
protected String testableString(Testable t) {
- //TODO
+ if (t instanceof StandaloneTestable) {
+ StandaloneTestable<?> testable = (StandaloneTestable) t;
+ String stage = testable.getStage().name();
+ String exception = causeString(testable.getException());
+ String errorCause = causeString(testable.errorCause());
+ return stage + exception + errorCause;
+ }
return "";
}
@Override
protected String deviceString(TestSuite suite) {
- //TODO
+ if (suite instanceof StandaloneTestSuite) {
+ StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite;
+ StringBuilder sb = new StringBuilder();
+ sb.append("═══ ").append(Colors.underline("ECTester version:")).append(" ").append(ECTesterStandalone.VERSION).append(System.lineSeparator());
+ sb.append("═══ ").append(Colors.underline("Library:")).append(" ").append(standaloneSuite.getLibrary().name()).append(System.lineSeparator());
+ return sb.toString();
+ }
return "";
}
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/output/XMLTestWriter.java b/src/cz/crcs/ectester/standalone/output/XMLTestWriter.java
index d2b16d8..812634f 100644
--- a/src/cz/crcs/ectester/standalone/output/XMLTestWriter.java
+++ b/src/cz/crcs/ectester/standalone/output/XMLTestWriter.java
@@ -4,9 +4,12 @@ import cz.crcs.ectester.common.output.BaseXMLTestWriter;
import cz.crcs.ectester.common.test.TestSuite;
import cz.crcs.ectester.common.test.Testable;
import cz.crcs.ectester.common.util.ByteUtil;
-import cz.crcs.ectester.standalone.test.KeyAgreementTestable;
-import cz.crcs.ectester.standalone.test.KeyGeneratorTestable;
-import cz.crcs.ectester.standalone.test.SignatureTestable;
+import cz.crcs.ectester.standalone.ECTesterStandalone;
+import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable;
+import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable;
+import cz.crcs.ectester.standalone.test.base.SignatureTestable;
+import cz.crcs.ectester.standalone.test.base.StandaloneTestable;
+import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
import org.w3c.dom.Element;
import javax.xml.parsers.ParserConfigurationException;
@@ -95,25 +98,59 @@ public class XMLTestWriter extends BaseXMLTestWriter {
return sigElem;
}
+ private Element stageElement(StandaloneTestable<?> t) {
+ Element result = doc.createElement("stage");
+ result.setTextContent(t.getStage().name());
+ return result;
+ }
+
+ private String causeObject(Object cause) {
+ if (cause == null) {
+ return "";
+ } else if (cause instanceof Exception) {
+ Exception ex = ((Exception) cause);
+ return ex.getClass().getCanonicalName() + " : " + ex.getMessage();
+ } else {
+ return cause.toString();
+ }
+ }
+
@Override
protected Element testableElement(Testable t) {
Element result = doc.createElement("test");
- if (t instanceof KeyGeneratorTestable) {
- result.setAttribute("type", "key-pair-generator");
- result.appendChild(kgtElement((KeyGeneratorTestable) t));
- } else if (t instanceof KeyAgreementTestable) {
- result.setAttribute("type", "key-agreement");
- result.appendChild(kaElement((KeyAgreementTestable) t));
- } else if (t instanceof SignatureTestable) {
- result.setAttribute("type", "signature");
- result.appendChild(sigElement((SignatureTestable) t));
+ if (t instanceof StandaloneTestable) {
+ StandaloneTestable<?> testable = (StandaloneTestable) t;
+ if (t instanceof KeyGeneratorTestable) {
+ result.setAttribute("type", "key-pair-generator");
+ result.appendChild(kgtElement((KeyGeneratorTestable) t));
+ } else if (t instanceof KeyAgreementTestable) {
+ result.setAttribute("type", "key-agreement");
+ result.appendChild(kaElement((KeyAgreementTestable) t));
+ } else if (t instanceof SignatureTestable) {
+ result.setAttribute("type", "signature");
+ result.appendChild(sigElement((SignatureTestable) t));
+ }
+ result.appendChild(stageElement(testable));
+ Element exception = doc.createElement("exception");
+ exception.setTextContent(causeObject(testable.getException()) + causeObject(testable.errorCause()));
+ result.appendChild(exception);
}
return result;
}
@Override
protected Element deviceElement(TestSuite suite) {
- //TODO
+ if (suite instanceof StandaloneTestSuite) {
+ StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite;
+ Element result = doc.createElement("device");
+ result.setAttribute("type", "library");
+ result.setAttribute("ectester", ECTesterStandalone.VERSION);
+
+ Element name = doc.createElement("name");
+ name.setTextContent(standaloneSuite.getLibrary().name());
+ result.appendChild(name);
+ return result;
+ }
return null;
}
}
diff --git a/src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java b/src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
index dfc6813..433624a 100644
--- a/src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
+++ b/src/cz/crcs/ectester/standalone/output/YAMLTestWriter.java
@@ -4,15 +4,19 @@ import cz.crcs.ectester.common.output.BaseYAMLTestWriter;
import cz.crcs.ectester.common.test.TestSuite;
import cz.crcs.ectester.common.test.Testable;
import cz.crcs.ectester.common.util.ByteUtil;
-import cz.crcs.ectester.standalone.test.KeyAgreementTestable;
-import cz.crcs.ectester.standalone.test.KeyGeneratorTestable;
-import cz.crcs.ectester.standalone.test.SignatureTestable;
+import cz.crcs.ectester.standalone.ECTesterStandalone;
+import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable;
+import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable;
+import cz.crcs.ectester.standalone.test.base.SignatureTestable;
+import cz.crcs.ectester.standalone.test.base.StandaloneTestable;
+import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite;
import java.io.PrintStream;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
/**
@@ -24,7 +28,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> keyObject(Key key) {
- Map<String, Object> kObject = new HashMap<>();
+ Map<String, Object> kObject = new LinkedHashMap<>();
if (key == null) {
return kObject;
}
@@ -35,7 +39,7 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> kaObject(KeyAgreementTestable kat) {
- Map<String, Object> katObject = new HashMap<>();
+ Map<String, Object> katObject = new LinkedHashMap<>();
katObject.put("algo", kat.getKa().getAlgorithm());
katObject.put("secret", ByteUtil.bytesToHex(kat.getSecret()));
@@ -48,10 +52,10 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> kgtObject(KeyGeneratorTestable kgt) {
- Map<String, Object> kgtObject = new HashMap<>();
+ Map<String, Object> kgtObject = new LinkedHashMap<>();
kgtObject.put("algo", kgt.getKpg().getAlgorithm());
- Map<String, Object> keypair = new HashMap<>();
+ Map<String, Object> keypair = new LinkedHashMap<>();
if (kgt.getKeyPair() != null) {
PublicKey pkey = kgt.getKeyPair().getPublic();
Map<String, Object> pubObject = keyObject(pkey);
@@ -67,32 +71,55 @@ public class YAMLTestWriter extends BaseYAMLTestWriter {
}
private Map<String, Object> sigObject(SignatureTestable sig) {
- Map<String, Object> sigObject = new HashMap<>();
+ Map<String, Object> sigObject = new LinkedHashMap<>();
sigObject.put("algo", sig.getSig().getAlgorithm());
sigObject.put("verified", sig.getVerified());
sigObject.put("raw", ByteUtil.bytesToHex(sig.getSignature()));
return sigObject;
}
+ private String causeObject(Object cause) {
+ if (cause == null) {
+ return "";
+ } else if (cause instanceof Exception) {
+ Exception ex = ((Exception) cause);
+ return ex.getClass().getCanonicalName() + " : " + ex.getMessage();
+ } else {
+ return cause.toString();
+ }
+ }
+
@Override
protected Map<String, Object> testableObject(Testable t) {
- Map<String, Object> result = new HashMap<>();
- if (t instanceof KeyGeneratorTestable) {
- result.put("type", "key-pair-generator");
- result.put("key-pair-generator", kgtObject((KeyGeneratorTestable) t));
- } else if (t instanceof KeyAgreementTestable) {
- result.put("type", "key-agreement");
- result.put("key-agreement", kaObject((KeyAgreementTestable) t));
- } else if (t instanceof SignatureTestable) {
- result.put("type", "signature");
- result.put("signature", sigObject((SignatureTestable) t));
+ Map<String, Object> result = new LinkedHashMap<>();
+ if (t instanceof StandaloneTestable) {
+ StandaloneTestable<?> testable = (StandaloneTestable) t;
+ if (t instanceof KeyGeneratorTestable) {
+ result.put("type", "key-pair-generator");
+ result.put("key-pair-generator", kgtObject((KeyGeneratorTestable) t));
+ } else if (t instanceof KeyAgreementTestable) {
+ result.put("type", "key-agreement");
+ result.put("key-agreement", kaObject((KeyAgreementTestable) t));
+ } else if (t instanceof SignatureTestable) {
+ result.put("type", "signature");
+ result.put("signature", sigObject((SignatureTestable) t));
+ }
+ result.put("stage", testable.getStage().name());
+ result.put("exception", causeObject(testable.getException()) + causeObject(testable.errorCause()));
}
return result;
}
@Override
protected Map<String, Object> deviceObject(TestSuite suite) {
- //TODO
+ if (suite instanceof StandaloneTestSuite) {
+ StandaloneTestSuite standaloneSuite = (StandaloneTestSuite) suite;
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("type", "library");
+ result.put("ectester", ECTesterStandalone.VERSION);
+ result.put("name", standaloneSuite.getLibrary().name());
+ return result;
+ }
return null;
}
}
diff --git a/src/cz/crcs/ectester/standalone/test/KeyAgreementTestable.java b/src/cz/crcs/ectester/standalone/test/KeyAgreementTestable.java
deleted file mode 100644
index de9356b..0000000
--- a/src/cz/crcs/ectester/standalone/test/KeyAgreementTestable.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package cz.crcs.ectester.standalone.test;
-
-import cz.crcs.ectester.common.test.BaseTestable;
-import cz.crcs.ectester.common.test.TestException;
-
-import javax.crypto.KeyAgreement;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.ECParameterSpec;
-
-/**
- * @author Jan Jancar johny@neuromancer.sk
- */
-public class KeyAgreementTestable extends BaseTestable {
- private KeyAgreement ka;
- private ECPrivateKey privateKey;
- private ECPublicKey publicKey;
- private KeyGeneratorTestable kgtPrivate;
- private KeyGeneratorTestable kgtPublic;
- private AlgorithmParameterSpec spec;
- private byte[] secret;
-
- public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey) {
- this.ka = ka;
- this.privateKey = privateKey;
- this.publicKey = publicKey;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, ECParameterSpec spec) {
- this(ka, privateKey, publicKey);
- this.spec = spec;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, ECParameterSpec spec) {
- this(ka, privateKey, null, spec);
- this.kgtPublic = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, ECParameterSpec spec) {
- this(ka, null, publicKey, spec);
- this.kgtPrivate = kgt;
- }
-
- public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, ECParameterSpec spec) {
- this(ka, (ECPrivateKey) null, null, spec);
- this.kgtPrivate = privKgt;
- this.kgtPublic = pubKgt;
- }
-
- public KeyAgreement getKa() {
- return ka;
- }
-
- public ECPublicKey getPublicKey() {
- return publicKey;
- }
-
- public ECPrivateKey getPrivateKey() {
- return privateKey;
- }
-
- public byte[] getSecret() {
- if (!hasRun) {
- return null;
- }
- return secret;
- }
-
- @Override
- public void run() throws TestException {
- if (kgtPrivate != null) {
- privateKey = (ECPrivateKey) kgtPrivate.getKeyPair().getPrivate();
- }
-
- if (kgtPublic != null) {
- publicKey = (ECPublicKey) kgtPublic.getKeyPair().getPublic();
- }
-
- try {
- if (spec != null) {
- ka.init(privateKey, spec);
- } else {
- ka.init(privateKey);
- }
- } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
- ok = false;
- error = true;
- hasRun = true;
- return;
- }
-
- try {
- ka.doPhase(publicKey, true);
- } catch (IllegalStateException e) {
- ok = false;
- hasRun = true;
- return;
- } catch (InvalidKeyException e) {
- ok = false;
- error = true;
- hasRun = true;
- return;
- }
-
- try {
- secret = ka.generateSecret();
- } catch (IllegalStateException isex) {
- ok = false;
- hasRun = true;
- return;
- } catch (UnsupportedOperationException uoe) {
- ok = false;
- error = true;
- hasRun = false;
- return;
- }
-
- ok = true;
- hasRun = true;
- }
-}
diff --git a/src/cz/crcs/ectester/standalone/test/SignatureTestable.java b/src/cz/crcs/ectester/standalone/test/SignatureTestable.java
deleted file mode 100644
index e434337..0000000
--- a/src/cz/crcs/ectester/standalone/test/SignatureTestable.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package cz.crcs.ectester.standalone.test;
-
-import cz.crcs.ectester.common.test.BaseTestable;
-import cz.crcs.ectester.common.test.TestException;
-
-import java.security.InvalidKeyException;
-import java.security.SecureRandom;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-
-public class SignatureTestable extends BaseTestable {
- private Signature sig;
- private ECPrivateKey signKey;
- private ECPublicKey verifyKey;
- private KeyGeneratorTestable kgt;
- private byte[] data;
- private byte[] signature;
- private boolean verified;
-
- public SignatureTestable(Signature sig, ECPrivateKey signKey, ECPublicKey verifyKey, byte[] data) {
- this.sig = sig;
- this.signKey = signKey;
- this.verifyKey = verifyKey;
- this.data = data;
- if (data == null) {
- SecureRandom random = new SecureRandom();
- this.data = new byte[32];
- random.nextBytes(this.data);
- }
- }
-
- public SignatureTestable(Signature sig, KeyGeneratorTestable kgt, byte[] data) {
- this(sig, null, null, data);
- this.kgt = kgt;
- }
-
- public Signature getSig() {
- return sig;
- }
-
- public byte[] getData() {
- return data;
- }
-
- public byte[] getSignature() {
- return signature;
- }
-
- public boolean getVerified() {
- return verified;
- }
-
- @Override
- public void run() throws TestException {
- if (kgt != null) {
- signKey = (ECPrivateKey) kgt.getKeyPair().getPrivate();
- verifyKey = (ECPublicKey) kgt.getKeyPair().getPublic();
- }
-
- try {
- sig.initSign(signKey);
- } catch (InvalidKeyException e) {
- throw new TestException(e);
- }
-
- try {
- sig.update(data);
- } catch (SignatureException e) {
- ok = false;
- hasRun = true;
- return;
- }
-
- try {
- signature = sig.sign();
- } catch (SignatureException e) {
- ok = false;
- hasRun = true;
- return;
- }
-
- try {
- sig.initVerify(verifyKey);
- } catch (InvalidKeyException e) {
- throw new TestException(e);
- }
-
- try {
- sig.update(data);
- } catch (SignatureException e) {
- ok = false;
- hasRun = true;
- return;
- }
-
- try {
- verified = sig.verify(signature);
- } catch (SignatureException e) {
- ok = false;
- hasRun = true;
- }
- ok = true;
- hasRun = true;
- }
-}
diff --git a/src/cz/crcs/ectester/standalone/test/KeyAgreementTest.java b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java
index 5f697c4..bfd39fc 100644
--- a/src/cz/crcs/ectester/standalone/test/KeyAgreementTest.java
+++ b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java
@@ -1,9 +1,8 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.base;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.SimpleTest;
import cz.crcs.ectester.common.test.TestCallback;
-import cz.crcs.ectester.common.test.TestException;
import java.util.Arrays;
@@ -32,7 +31,8 @@ public class KeyAgreementTest extends SimpleTest<KeyAgreementTestable> {
return new KeyAgreementTest(ka, new TestCallback<KeyAgreementTestable>() {
@Override
public Result apply(KeyAgreementTestable keyAgreementTestable) {
- return new Result(Result.Value.fromExpected(expected, keyAgreementTestable.ok(), keyAgreementTestable.error()));
+ Result.Value value = Result.Value.fromExpected(expected, keyAgreementTestable.ok(), keyAgreementTestable.error());
+ return new Result(value, value.description());
}
});
}
@@ -43,15 +43,7 @@ public class KeyAgreementTest extends SimpleTest<KeyAgreementTestable> {
@Override
public String getDescription() {
- return "KeyAgreement " + testable.getKa().getAlgorithm();
- }
-
- @Override
- public void run() throws TestException {
- if (hasRun)
- return;
- testable.run();
- result = callback.apply(testable);
- hasRun = true;
+ String keyAlgo = testable.getKeyAlgorithm() == null ? "" : " (" + testable.getKeyAlgorithm() + ")";
+ return "KeyAgreement " + testable.getKa().getAlgorithm() + keyAlgo;
}
}
diff --git a/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
new file mode 100644
index 0000000..1382c28
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java
@@ -0,0 +1,170 @@
+package cz.crcs.ectester.standalone.test.base;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECParameterSpec;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class KeyAgreementTestable extends StandaloneTestable<KeyAgreementTestable.KeyAgreementStage> {
+ private KeyAgreement ka;
+ private ECPrivateKey privateKey;
+ private ECPublicKey publicKey;
+ private KeyGeneratorTestable kgtPrivate;
+ private KeyGeneratorTestable kgtPublic;
+ private AlgorithmParameterSpec spec;
+ private String keyAlgo;
+ private byte[] secret;
+ private SecretKey derived;
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey) {
+ this.ka = ka;
+ this.privateKey = privateKey;
+ this.publicKey = publicKey;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, String keyAlgo) {
+ this(ka, privateKey, publicKey);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, ECParameterSpec spec) {
+ this(ka, privateKey, publicKey);
+ this.spec = spec;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPrivateKey privateKey, ECPublicKey publicKey, ECParameterSpec spec, String keyAlgo) {
+ this(ka, privateKey, publicKey, spec);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, ECParameterSpec spec) {
+ this(ka, privateKey, null, spec);
+ this.kgtPublic = kgt;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable kgt, ECPrivateKey privateKey, ECParameterSpec spec, String keyAlgo) {
+ this(ka, kgt, privateKey, spec);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, ECParameterSpec spec) {
+ this(ka, null, publicKey, spec);
+ this.kgtPrivate = kgt;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, ECPublicKey publicKey, KeyGeneratorTestable kgt, ECParameterSpec spec, String keyAlgo) {
+ this(ka, publicKey, kgt, spec);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, ECParameterSpec spec) {
+ this(ka, (ECPrivateKey) null, null, spec);
+ this.kgtPrivate = privKgt;
+ this.kgtPublic = pubKgt;
+ }
+
+ public KeyAgreementTestable(KeyAgreement ka, KeyGeneratorTestable privKgt, KeyGeneratorTestable pubKgt, ECParameterSpec spec, String keyAlgo) {
+ this(ka, privKgt, pubKgt, spec);
+ this.keyAlgo = keyAlgo;
+ }
+
+ public String getKeyAlgorithm() {
+ return keyAlgo;
+ }
+
+ public KeyAgreement getKa() {
+ return ka;
+ }
+
+ public ECPublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ public ECPrivateKey getPrivateKey() {
+ return privateKey;
+ }
+
+ public byte[] getSecret() {
+ if (!hasRun) {
+ return null;
+ }
+ return secret;
+ }
+
+ public SecretKey getDerivedKey() {
+ if (!hasRun) {
+ return null;
+ }
+ return derived;
+ }
+
+ @Override
+ public void run() {
+ try {
+ stage = KeyAgreementStage.GetPrivate;
+ if (kgtPrivate != null) {
+ privateKey = (ECPrivateKey) kgtPrivate.getKeyPair().getPrivate();
+ }
+
+ stage = KeyAgreementStage.GetPublic;
+ if (kgtPublic != null) {
+ publicKey = (ECPublicKey) kgtPublic.getKeyPair().getPublic();
+ }
+
+ stage = KeyAgreementStage.Init;
+ try {
+ if (spec != null) {
+ ka.init(privateKey, spec);
+ } else {
+ ka.init(privateKey);
+ }
+ } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = KeyAgreementStage.DoPhase;
+ try {
+ ka.doPhase(publicKey, true);
+ } catch (IllegalStateException | InvalidKeyException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = KeyAgreementStage.GenerateSecret;
+ try {
+ if (keyAlgo != null) {
+ derived = ka.generateSecret(keyAlgo);
+ secret = derived.getEncoded();
+ } else {
+ secret = ka.generateSecret();
+ }
+ } catch (IllegalStateException | UnsupportedOperationException e) {
+ failOnException(e);
+ return;
+ }
+
+ ok = true;
+ } catch (Exception ex) {
+ ok = false;
+ error = true;
+ errorCause = ex;
+ }
+ hasRun = true;
+ }
+
+ public enum KeyAgreementStage {
+ GetPrivate,
+ GetPublic,
+ Init,
+ DoPhase,
+ GenerateSecret
+ }
+}
diff --git a/src/cz/crcs/ectester/standalone/test/KeyGeneratorTest.java b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java
index 93273ca..b232456 100644
--- a/src/cz/crcs/ectester/standalone/test/KeyGeneratorTest.java
+++ b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java
@@ -1,9 +1,8 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.base;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.SimpleTest;
import cz.crcs.ectester.common.test.TestCallback;
-import cz.crcs.ectester.common.test.TestException;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -17,7 +16,8 @@ public class KeyGeneratorTest extends SimpleTest<KeyGeneratorTestable> {
return new KeyGeneratorTest(kg, new TestCallback<KeyGeneratorTestable>() {
@Override
public Result apply(KeyGeneratorTestable keyGenerationTestable) {
- return new Result(Result.Value.fromExpected(expected, keyGenerationTestable.ok(), keyGenerationTestable.error()));
+ Result.Value value = Result.Value.fromExpected(expected, keyGenerationTestable.ok(), keyGenerationTestable.error());
+ return new Result(value, value.description());
}
});
}
@@ -30,13 +30,4 @@ public class KeyGeneratorTest extends SimpleTest<KeyGeneratorTestable> {
public String getDescription() {
return "KeyPairGenerator " + testable.getKpg().getAlgorithm();
}
-
- @Override
- public void run() throws TestException {
- if (hasRun)
- return;
- testable.run();
- result = callback.apply(testable);
- hasRun = true;
- }
}
diff --git a/src/cz/crcs/ectester/standalone/test/KeyGeneratorTestable.java b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
index 3fca168..c05d6e3 100644
--- a/src/cz/crcs/ectester/standalone/test/KeyGeneratorTestable.java
+++ b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java
@@ -1,14 +1,14 @@
-package cz.crcs.ectester.standalone.test;
-
-import cz.crcs.ectester.common.test.BaseTestable;
-import cz.crcs.ectester.common.test.TestException;
+package cz.crcs.ectester.standalone.test.base;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.spec.ECParameterSpec;
-public class KeyGeneratorTestable extends BaseTestable {
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class KeyGeneratorTestable extends StandaloneTestable<KeyGeneratorTestable.KeyGeneratorStage> {
private KeyPair kp;
private KeyPairGenerator kpg;
private int keysize = 0;
@@ -37,20 +37,34 @@ public class KeyGeneratorTestable extends BaseTestable {
}
@Override
- public void run() throws TestException {
+ public void run() {
try {
- if (spec != null) {
- kpg.initialize(spec);
- } else if (keysize != 0) {
- kpg.initialize(keysize);
+ stage = KeyGeneratorStage.Init;
+ try {
+ if (spec != null) {
+ kpg.initialize(spec);
+ } else if (keysize != 0) {
+ kpg.initialize(keysize);
+ }
+ } catch (InvalidAlgorithmParameterException e) {
+ failOnException(e);
+ return;
}
- } catch (InvalidAlgorithmParameterException e) {
- hasRun = true;
+
+ stage = KeyGeneratorStage.GenKeyPair;
+ kp = kpg.genKeyPair();
+
+ ok = true;
+ } catch (Exception ex) {
ok = false;
- return;
+ error = true;
+ errorCause = ex;
}
- kp = kpg.genKeyPair();
hasRun = true;
- ok = true;
+ }
+
+ public enum KeyGeneratorStage {
+ Init,
+ GenKeyPair
}
}
diff --git a/src/cz/crcs/ectester/standalone/test/SignatureTest.java b/src/cz/crcs/ectester/standalone/test/base/SignatureTest.java
index 9746b91..d8b3e0f 100644
--- a/src/cz/crcs/ectester/standalone/test/SignatureTest.java
+++ b/src/cz/crcs/ectester/standalone/test/base/SignatureTest.java
@@ -1,9 +1,8 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.base;
import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.SimpleTest;
import cz.crcs.ectester.common.test.TestCallback;
-import cz.crcs.ectester.common.test.TestException;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -17,7 +16,8 @@ public class SignatureTest extends SimpleTest<SignatureTestable> {
return new SignatureTest(kg, new TestCallback<SignatureTestable>() {
@Override
public Result apply(SignatureTestable signatureTestable) {
- return new Result(Result.Value.fromExpected(expected, signatureTestable.ok(), signatureTestable.error()));
+ Result.Value value = Result.Value.fromExpected(expected, signatureTestable.ok(), signatureTestable.error());
+ return new Result(value, value.description());
}
});
}
@@ -30,13 +30,4 @@ public class SignatureTest extends SimpleTest<SignatureTestable> {
public String getDescription() {
return "Signature " + testable.getSig().getAlgorithm();
}
-
- @Override
- public void run() throws TestException {
- if (hasRun)
- return;
- testable.run();
- result = callback.apply(testable);
- hasRun = true;
- }
}
diff --git a/src/cz/crcs/ectester/standalone/test/base/SignatureTestable.java b/src/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
new file mode 100644
index 0000000..b8db7b8
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/test/base/SignatureTestable.java
@@ -0,0 +1,130 @@
+package cz.crcs.ectester.standalone.test.base;
+
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class SignatureTestable extends StandaloneTestable<SignatureTestable.SignatureStage> {
+ private Signature sig;
+ private ECPrivateKey signKey;
+ private ECPublicKey verifyKey;
+ private KeyGeneratorTestable kgt;
+ private byte[] data;
+ private byte[] signature;
+ private boolean verified;
+
+ public SignatureTestable(Signature sig, ECPrivateKey signKey, ECPublicKey verifyKey, byte[] data) {
+ this.sig = sig;
+ this.signKey = signKey;
+ this.verifyKey = verifyKey;
+ this.data = data;
+ if (data == null) {
+ SecureRandom random = new SecureRandom();
+ this.data = new byte[64];
+ random.nextBytes(this.data);
+ }
+ }
+
+ public SignatureTestable(Signature sig, KeyGeneratorTestable kgt, byte[] data) {
+ this(sig, null, null, data);
+ this.kgt = kgt;
+ }
+
+ public Signature getSig() {
+ return sig;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ public byte[] getSignature() {
+ return signature;
+ }
+
+ public boolean getVerified() {
+ return verified;
+ }
+
+ @Override
+ public void run() {
+ try {
+ stage = SignatureStage.GetKeys;
+ if (kgt != null) {
+ signKey = (ECPrivateKey) kgt.getKeyPair().getPrivate();
+ verifyKey = (ECPublicKey) kgt.getKeyPair().getPublic();
+ }
+
+ stage = SignatureStage.InitSign;
+ try {
+ sig.initSign(signKey);
+ } catch (InvalidKeyException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.UpdateSign;
+ try {
+ sig.update(data);
+ } catch (SignatureException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.Sign;
+ try {
+ signature = sig.sign();
+ } catch (SignatureException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.InitVerify;
+ try {
+ sig.initVerify(verifyKey);
+ } catch (InvalidKeyException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.UpdateVerify;
+ try {
+ sig.update(data);
+ } catch (SignatureException e) {
+ failOnException(e);
+ return;
+ }
+
+ stage = SignatureStage.Verify;
+ try {
+ verified = sig.verify(signature);
+ } catch (SignatureException e) {
+ failOnException(e);
+ return;
+ }
+
+ ok = verified;
+ } catch (Exception ex) {
+ ok = false;
+ error = true;
+ errorCause = ex;
+ }
+ hasRun = true;
+ }
+
+ public enum SignatureStage {
+ GetKeys,
+ InitSign,
+ UpdateSign,
+ Sign,
+ InitVerify,
+ UpdateVerify,
+ Verify
+ }
+}
diff --git a/src/cz/crcs/ectester/standalone/test/base/StandaloneTestable.java b/src/cz/crcs/ectester/standalone/test/base/StandaloneTestable.java
new file mode 100644
index 0000000..47bffc1
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/test/base/StandaloneTestable.java
@@ -0,0 +1,25 @@
+package cz.crcs.ectester.standalone.test.base;
+
+import cz.crcs.ectester.common.test.BaseTestable;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public abstract class StandaloneTestable<T extends Enum<T>> extends BaseTestable {
+ protected T stage;
+ protected Exception exception;
+
+ public T getStage() {
+ return stage;
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+
+ protected void failOnException(Exception ex) {
+ ok = false;
+ hasRun = true;
+ exception = ex;
+ }
+}
diff --git a/src/cz/crcs/ectester/standalone/test/StandaloneDefaultSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
index 42d2e54..1c14ecc 100644
--- a/src/cz/crcs/ectester/standalone/test/StandaloneDefaultSuite.java
+++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneDefaultSuite.java
@@ -1,4 +1,4 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.suites;
import cz.crcs.ectester.common.cli.TreeCommandLine;
import cz.crcs.ectester.common.ec.EC_Curve;
@@ -9,11 +9,13 @@ import cz.crcs.ectester.standalone.ECTesterStandalone;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent;
import cz.crcs.ectester.standalone.consts.SignatureIdent;
+import cz.crcs.ectester.standalone.test.base.*;
import javax.crypto.KeyAgreement;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.spec.ECParameterSpec;
+import java.util.Optional;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -21,18 +23,42 @@ import java.security.spec.ECParameterSpec;
public class StandaloneDefaultSuite extends StandaloneTestSuite {
public StandaloneDefaultSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli) {
- super(writer, cfg, cli, "default", "The default test suite run basic support of ECDH and ECDSA.");
+ super(writer, cfg, cli, "default", "The default test suite run basic support of ECDH and ECDSA.", "Supports options:", "\t - gt/kpg-type", "\t - kt/ka-type", "\t - st/sig-type", "\t - key-type");
}
@Override
protected void runTests() throws Exception {
- String kpgAlgo = cli.getOptionValue("test.kpg-type", "EC");
+ String kpgAlgo = cli.getOptionValue("test.kpg-type");
String kaAlgo = cli.getOptionValue("test.ka-type");
String sigAlgo = cli.getOptionValue("test.sig-type");
+ String keyAlgo = cli.getOptionValue("test.key-type", "AES");
+
+
+ KeyPairGeneratorIdent kpgIdent;
+ if (kpgAlgo == null) {
+ // try EC, if not, fail with: need to specify kpg algo.
+ Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream()
+ .filter((ident) -> ident.contains("EC"))
+ .findFirst();
+ if (kpgIdentOpt.isPresent()) {
+ kpgIdent = kpgIdentOpt.get();
+ } else {
+ System.err.println("The default KeyPairGenerator algorithm type of \"EC\" was not found. Need to specify a type.");
+ return;
+ }
+ } else {
+ // try the specified, if not, fail with: wrong kpg algo/not found.
+ Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream()
+ .filter((ident) -> ident.contains(kpgAlgo))
+ .findFirst();
+ if (kpgIdentOpt.isPresent()) {
+ kpgIdent = kpgIdentOpt.get();
+ } else {
+ System.err.println("The KeyPairGenerator algorithm type of \"" + kpgAlgo + "\" was not found.");
+ return;
+ }
+ }
- KeyPairGeneratorIdent kpgIdent = cfg.selected.getKPGs().stream()
- .filter((ident) -> ident.contains(kpgAlgo))
- .findFirst().get();
KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider());
KeyGeneratorTestable kgtOne;
@@ -63,7 +89,13 @@ public class StandaloneDefaultSuite extends StandaloneTestSuite {
for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) {
if (kaAlgo == null || kaIdent.contains(kaAlgo)) {
KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider());
- doTest(KeyAgreementTest.expect(new KeyAgreementTestable(ka, kgtOne, kgtOther, spec), Result.ExpectedValue.SUCCESS));
+ KeyAgreementTestable testable;
+ if (kaIdent.requiresKeyAlgo()) {
+ testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec, keyAlgo);
+ } else {
+ testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec);
+ }
+ doTest(KeyAgreementTest.expect(testable, Result.ExpectedValue.SUCCESS));
}
}
for (SignatureIdent sigIdent : cfg.selected.getSigs()) {
diff --git a/src/cz/crcs/ectester/standalone/test/StandaloneTestSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
index ad404c8..e4e0013 100644
--- a/src/cz/crcs/ectester/standalone/test/StandaloneTestSuite.java
+++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java
@@ -1,12 +1,10 @@
-package cz.crcs.ectester.standalone.test;
+package cz.crcs.ectester.standalone.test.suites;
import cz.crcs.ectester.common.cli.TreeCommandLine;
import cz.crcs.ectester.common.output.TestWriter;
import cz.crcs.ectester.common.test.TestSuite;
-import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.ECTesterStandalone;
-
-import java.security.NoSuchAlgorithmException;
+import cz.crcs.ectester.standalone.libs.ProviderECLibrary;
/**
* @author Jan Jancar johny@neuromancer.sk
@@ -15,9 +13,13 @@ public abstract class StandaloneTestSuite extends TestSuite {
TreeCommandLine cli;
ECTesterStandalone.Config cfg;
- public StandaloneTestSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli, String name, String description) {
+ public StandaloneTestSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli, String name, String... description) {
super(writer, name, description);
this.cfg = cfg;
this.cli = cli;
}
+
+ public ProviderECLibrary getLibrary() {
+ return cfg.selected;
+ }
}