aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.appveyor.yml18
-rw-r--r--.gitignore20
-rw-r--r--.gitmodules9
-rw-r--r--.travis.yml6
-rw-r--r--LICENSE2
-rw-r--r--README.md197
-rw-r--r--applet/gppro_upload.bat7
-rwxr-xr-xapplet/gppro_upload.sh5
-rw-r--r--applet/gppro_upload_emv.bat1
-rwxr-xr-xapplet/gppro_upload_emv.sh1
-rw-r--r--build-applet.xml17
-rw-r--r--build-standalone.xml42
-rw-r--r--docs/CURVES.md76
-rw-r--r--docs/FORMAT.md6
-rw-r--r--docs/IMPLEMENTATIONS.md552
-rw-r--r--docs/LIBS.md84
-rw-r--r--docs/TESTS.md153
-rw-r--r--ext/ant-javacard.jarbin9346 -> 14842 bytes
-rw-r--r--ext/globalplatform-2_1_1/gp211.jarbin2766 -> 0 bytes
-rw-r--r--ext/globalplatform-2_1_1/org/globalplatform/javacard/globalplatform.expbin1868 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/api_export_files/java/io/javacard/io.expbin212 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/api_export_files/java/lang/javacard/lang.expbin881 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/api_export_files/java/rmi/javacard/rmi.expbin280 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/api_export_files/javacard/framework/javacard/framework.expbin6750 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/api_export_files/javacard/framework/service/javacard/service.expbin2901 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/api_export_files/javacard/security/javacard/security.expbin7205 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/api_export_files/javacardx/crypto/javacard/crypto.expbin1282 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/bin/apdutool15
-rw-r--r--ext/java_card_kit-2_2_1/bin/capdump15
-rw-r--r--ext/java_card_kit-2_2_1/bin/capgen15
-rw-r--r--ext/java_card_kit-2_2_1/bin/converter15
-rw-r--r--ext/java_card_kit-2_2_1/bin/crefbin590311 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/bin/exp2text15
-rw-r--r--ext/java_card_kit-2_2_1/bin/jcwde15
-rw-r--r--ext/java_card_kit-2_2_1/bin/scriptgen15
-rw-r--r--ext/java_card_kit-2_2_1/bin/verifycap15
-rw-r--r--ext/java_card_kit-2_2_1/bin/verifyexp15
-rw-r--r--ext/java_card_kit-2_2_1/bin/verifyrev15
-rw-r--r--ext/java_card_kit-2_2_1/lib/apduio.jarbin18371 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/apdutool.jarbin25249 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/api.jarbin125003 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/capdump.jarbin4397 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/converter.jarbin641460 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/installer.jarbin29810 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/javacardframework.jarbin82345 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/jcclientsamples.jarbin18202 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/jcrmiclientframework.jarbin35705 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/jcwde.jarbin76411 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/offcardverifier.jarbin149207 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_1/lib/scriptgen.jarbin12459 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/java/io/javacard/io.expbin212 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/java/lang/javacard/lang.expbin881 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/java/rmi/javacard/rmi.expbin280 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacard/framework/javacard/framework.expbin7040 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacard/framework/service/javacard/service.expbin2901 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacard/security/javacard/security.expbin8989 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacardx/apdu/javacard/apdu.expbin113 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacardx/biometry/javacard/biometry.expbin2254 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacardx/crypto/javacard/crypto.expbin1382 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacardx/external/javacard/external.expbin857 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/math/javacard/math.expbin812 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/tlv/javacard/tlv.expbin3011 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/util/intx/javacard/intx.expbin309 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/util/javacard/util.expbin819 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/bin/apdutool15
-rw-r--r--ext/java_card_kit-2_2_2/bin/capdump15
-rw-r--r--ext/java_card_kit-2_2_2/bin/capgen15
-rw-r--r--ext/java_card_kit-2_2_2/bin/converter15
-rw-r--r--ext/java_card_kit-2_2_2/bin/crefbin735003 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/bin/exp2text15
-rw-r--r--ext/java_card_kit-2_2_2/bin/jcwde15
-rw-r--r--ext/java_card_kit-2_2_2/bin/libjpcsclite.sobin5803 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/bin/scriptgen15
-rw-r--r--ext/java_card_kit-2_2_2/bin/verifycap15
-rw-r--r--ext/java_card_kit-2_2_2/bin/verifyexp15
-rw-r--r--ext/java_card_kit-2_2_2/bin/verifyrev15
-rw-r--r--ext/java_card_kit-2_2_2/lib/apduio.jarbin48313 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/apdutool.jarbin26302 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/api.jarbin175768 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/api_16.jarbin145072 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/capdump.jarbin4369 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/converter.jarbin640317 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/installer.jarbin30035 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/javacardframework.jarbin95149 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/jcclientsamples.jarbin23754 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/jcrmiclientframework.jarbin31335 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/jcwde.jarbin80671 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/jcwde_16.jarbin69477 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/offcardverifier.jarbin147387 -> 0 bytes
-rw-r--r--ext/java_card_kit-2_2_2/lib/scriptgen.jarbin12382 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/COPYRIGHT.html171
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/java/io/javacard/io.expbin212 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/java/lang/javacard/lang.expbin881 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/java/rmi/javacard/rmi.expbin280 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacard/framework/javacard/framework.expbin7077 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacard/framework/service/javacard/service.expbin2901 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacard/security/javacard/security.expbin10533 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacardx/apdu/javacard/apdu.expbin113 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacardx/biometry/javacard/biometry.expbin2254 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacardx/crypto/javacard/crypto.expbin1862 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacardx/external/javacard/external.expbin857 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/math/javacard/math.expbin812 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/tlv/javacard/tlv.expbin3011 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/util/intx/javacard/intx.expbin309 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/util/javacard/util.expbin819 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/legal/Distribution_ReadME.txt21
-rw-r--r--ext/java_card_kit-3_0_3/legal/THIRDPARTYREADME.txt1246
-rw-r--r--ext/java_card_kit-3_0_3/lib/api_classic.jarbin43109 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/lib/api_connected.jarbin142812 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/lib/logging.properties64
-rw-r--r--ext/java_card_kit-3_0_3/lib/tools.jarbin1452414 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/shared/Java_clr_hori.gifbin3500 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/shared/Java_clr_hori_interval.gifbin1725 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/shared/Java_clr_hori_small.gifbin1267 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/shared/downicon.gifbin91 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/shared/oracle.gifbin1932 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/shared/smallOracleLogo.gifbin2059 -> 0 bytes
-rw-r--r--ext/java_card_kit-3_0_3/shared/topicon.gifbin93 -> 0 bytes
m---------ext/libs0
m---------ext/mscng0
m---------ext/sdks0
-rw-r--r--ext/visa_openplatform-2_0/visa/openplatform/javacard/openplatform.expbin1294 -> 0 bytes
-rw-r--r--ext/visa_openplatform-2_0/visaop20.jarbin26832 -> 0 bytes
-rw-r--r--lib/commons-cli-1.3.1-javadoc.jarbin169756 -> 0 bytes
-rw-r--r--lib/commons-cli-1.3.1.jarbin52988 -> 0 bytes
-rw-r--r--lib/commons-cli-1.4-javadoc.jarbin0 -> 179154 bytes
-rw-r--r--lib/commons-cli-1.4.jarbin0 -> 53820 bytes
-rw-r--r--nbproject/dist-build.xml11
-rwxr-xr-xnbproject/keystorebin0 -> 3987 bytes
-rw-r--r--nbproject/reader/manifest.mf2
-rw-r--r--nbproject/reader/project.properties8
-rw-r--r--nbproject/standalone/manifest.mf2
-rw-r--r--nbproject/standalone/project.properties10
-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
-rwxr-xr-xutil/plot_dh.py60
-rwxr-xr-xutil/plot_gen.py66
386 files changed, 14349 insertions, 4285 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100755
index 0000000..051d974
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,18 @@
+version: '{build}'
+image: Visual Studio 2017
+
+branches:
+ except:
+ - gh-pages
+
+environment:
+ JAVA_HOME: C:\Program Files\Java\jdk1.8.0
+
+install:
+ - cinst ant
+ - git submodule update --init --recursive
+
+build_script:
+ - ant -f build-applet.xml build
+ - ant -f build-reader.xml package
+ - ant -f build-standalone.xml package \ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1953275..8f7585a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
# Built artifacts in /dist and /applet.
+/build/
/dist/lib/
/dist/ECTesterReader.jar
/dist/ECTesterReader-dist.jar
@@ -8,7 +9,26 @@
/dist/ECTesterStandalone-dist.jar
/applet/ectester.cap
+# Test runs in /dist
+/dist/*.default
+/dist/*.test-vectors
+/dist/*.compression
+/dist/*.cofactor
+/dist/*.composite
+/dist/*.wrong
+/dist/*.invalid
+/dist/*.twist
+/dist/*.miscellaneous
+/dist/*.degenerate
+/dist/*.edge-cases
+/dist/*.xml
+
# Built binaries in /src.
/src/**/*.a
/src/**/*.o
+/src/**/*.obj
/src/**/*.so
+/src/**/*.dll
+/src/**/*.exp
+/src/**/*.lib
+/src/**/*.pdb
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..0fb6b09
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,9 @@
+[submodule "ext/sdks"]
+ path = ext/sdks
+ url = https://github.com/martinpaljak/oracle_javacard_sdks
+[submodule "ext/libs"]
+ path = ext/libs
+ url = https://github.com/J08nY/javacard-libs
+[submodule "ext/mscng"]
+ path = ext/mscng
+ url = https://github.com/J08nY/mscng-dev-kit
diff --git a/.travis.yml b/.travis.yml
index 62681d6..453c523 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,8 @@ addons:
packages:
- libtomcrypt-dev
- libtommath-dev
+ - libssl-dev
+ - libcrypto++-dev
- gcc-6
- g++-6
language: java
@@ -18,6 +20,9 @@ script:
- ant -f build-reader.xml package
- ant -f build-standalone.xml package
+before_deploy:
+ - zip "dist/ECTester.zip" "dist/ECTesterReader-dist.jar" "dist/ECTesterReader.jar" "applet/ectester.cap" "dist/ECTesterStandalone-dist.jar" "dist/ECTesterStandalone.jar"
+
deploy:
provider: releases
api_key:
@@ -28,6 +33,7 @@ deploy:
- "applet/ectester.cap"
- "dist/ECTesterStandalone-dist.jar"
- "dist/ECTesterStandalone.jar"
+ - "dist/ECTester.zip"
skip_cleanup: true
on:
tags: true
diff --git a/LICENSE b/LICENSE
index 21ecc94..82e5bee 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2016-2017
+Copyright (c) 2016-2018
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 6184b84..bed5e62 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,14 @@
# ECTester
-[![Build status](https://api.travis-ci.org/crocs-muni/ECTester.svg?branch=master)](https://travis-ci.org/crocs-muni/ECTester) [![GitHub release](https://img.shields.io/github/release/crocs-muni/ECTEster.svg)](https://github.com/crocs-muni/ECTester/releases) [![license](https://img.shields.io/github/license/crocs-muni/ECTester.svg)](https://github.com/crocs-muni/ECTester/blob/master/LICENSE)
+[![Build status](https://api.travis-ci.org/crocs-muni/ECTester.svg?branch=master)](https://travis-ci.org/crocs-muni/ECTester) [![Build status](https://ci.appveyor.com/api/projects/status/02kcaf52op89910u?svg=true)](https://ci.appveyor.com/project/J08nY/ectester-cm6ng) [![GitHub release](https://img.shields.io/github/release/crocs-muni/ECTEster.svg)](https://github.com/crocs-muni/ECTester/releases) [![license](https://img.shields.io/github/license/crocs-muni/ECTester.svg)](https://github.com/crocs-muni/ECTester/blob/master/LICENSE) [![docs](https://img.shields.io/badge/docs-github.io-brightgreen.svg)](https://crocs-muni.github.io/ECTester/)
Tests support and behavior of elliptic curve cryptography implementations on JavaCards (`TYPE_EC_FP` and `TYPE_EC_F2M`) and on selected software libraries.
+For more information on ECC support on JavaCards see the [github page](https://crocs-muni.github.io/ECTester/), with results, tables and docs.
## Build
ECTester uses ant. There are three parts of ECTester, the JavaCard applet used for testing, the reader app which controls it and the standalone app which tests software libraries.
```bash
+git submodule update --init --recursive # To initialize submodules.
ant -f build-reader.xml package # To build the reader tool (jar) -> "dist/ECTesterReader.jar"
ant -f build-standalone.xml package # To build the standalone tool (jar) -> "dist/ECTesterStandalone.jar"
ant -f build-applet.xml build # To build the applet (cap) -> "applet/ectester.cap".
@@ -17,7 +19,7 @@ The standalone build tries building test binaries for all the supported librarie
## JavaCard testing
1. Upload `!uploader/ectester.cap` using your favorite tool (e.g., [GlobalPlatformPro tool](https://github.com/martinpaljak/GlobalPlatform))
-2. Run `java -jar dist/ECTesterReader.jar -t -a`
+2. Run `java -jar dist/ECTesterReader.jar -t`
3. Inspect output log with annotated results
Following operations are tested:
@@ -26,7 +28,6 @@ Following operations are tested:
- Setting of custom curve and KeyPair generation
- Generation of shared secret via ECDH
- Signature via ECDSA
-- Behavior of card when invalid curves/points are provided (should fail)
See `java -jar ECTesterReader.jar -h` for more.
@@ -37,6 +38,10 @@ See `java -jar ECTesterReader.jar -h` for more.
-t,--test <test_suite> Test ECC support. [test_suite]:
- default:
- invalid:
+ - compression:
+ - twist:
+ - degenerate:
+ - cofactor:
- wrong:
- composite:
- test-vectors:
@@ -80,6 +85,9 @@ See `java -jar ECTesterReader.jar -h` for more.
text,yml,xml.
-f,--fresh Generate fresh keys (set domain
parameters before every generation).
+ --cleanup Send the cleanup command trigerring
+ JCSystem.requestObjectDeletion()
+ after some operations.
-s,--simulate Simulate a card with jcardsim instead
of using a terminal.
-y,--yes Accept all warnings and prompts.
@@ -89,6 +97,8 @@ See `java -jar ECTesterReader.jar -h` for more.
constants.
-sig,--sig-type <type> Set Signature object [type],
corresponds to JC.Signature constants.
+ -C,--color Print stuff with color, requires ANSI
+ terminal.
```
### Actions
@@ -103,8 +113,10 @@ For format of this file see [FORMAT](docs/FORMAT.md).
#### Test
`-t / --test [test_suite]`
-Perform support and performance tests of ECC.
+Perform support,performance and vulnerability tests of ECC.
+Use with `-o / --output [out_type:]<out_file>` to output the test results to a file.
+For possible formats of this file see [FORMAT](docs/FORMAT.md).
For more info about the test suites see [TESTS](docs/TESTS.md).
#### Generate
@@ -112,20 +124,24 @@ For more info about the test suites see [TESTS](docs/TESTS.md).
Generates batches of EC keypairs and exports them.
Use with `-o / --output [out_file]` to output the generated keys to a file.
+For format of this file see [FORMAT](docs/FORMAT.md).
#### ECDH
`-dh / --ecdh [count]`
Performs ECDH.
Use with `-o / --output [out_file]` to output into a file.
+For format of this file see [FORMAT](docs/FORMAT.md).
Respects the KeyAgreement type specified in `-ka / --ka-type [type]`.
+
#### ECDSA
`-dsa / --ecdsa [count]`
Performs ECDSA.
Useful with `-i / --input [in_file]` to sign the contents of a file.
Use with `-o / --output [out_file]` to output into a file.
+For format of these files see [FORMAT](docs/FORMAT.md).
Respects the Signature type specified in `-sig / --sig-type [type]`.
#### List named curves
@@ -139,39 +155,63 @@ With the format: `category/name`.
For example:
`secg/secp192r1` identifies the SECG 192 bit prime field curve known as `secp192r1`.
-For more info about the curves see [CURVES](docs/CURVES.md).
+For more info about the curves and curve categories see [CURVES](docs/CURVES.md).
### Example
- > java -jar ECTesterReader.jar -t -a -s
+Snippet below shows running the default test suite while simulating(`-s`), so using JCardSim.
+This shows that JCardsim simulates 112b Fp support with default curve present and supports ECDH, ECDHC and ECDSA.
+
+ > java -jar ECTesterReader.jar -t -s
â•â•â• Running test suite: default â•â•â•
- â•â•â• The default test suite run basic support of ECDH and ECDSA.
+ â•â•â• The default test suite tests basic support of ECDH and ECDSA.
+ â•â•â• Date: 2018.05.02 20:29:38
+ â•â•â• ECTester version: v0.2.0
â•â•â• Card ATR: 3bfa1800008131fe454a434f5033315632333298
- NOK ┳ Tests of 112b ALG_EC_FP support. Some. ┃ FAILURE ┃ Some sub-tests did not have the expected result.
- ┣ OK ┠Allocated both keypairs 112b ALG_EC_FP ┃ SUCCESS ┃ 50 ms ┃ OK (0x9000) OK (0x9000)
- ┣ OK ┠Generated both keypairs ┃ SUCCESS ┃ 37 ms ┃ OK (0x9000) OK (0x9000)
- ┣ OK ┠Set custom curve parameters on both keypairs ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000) OK (0x9000)
- ┣ OK ┠Generated both keypairs ┃ SUCCESS ┃ 16 ms ┃ OK (0x9000) OK (0x9000)
- ┣ OK ┳ Test of the ALG_EC_SVDP_DH KeyAgreement. ┃ SUCCESS ┃ All sub-tests had the expected result.
- ┃ ┣ OK ┠Allocated KeyAgreement(ALG_EC_SVDP_DH) object ┃ SUCCESS ┃ 2 ms ┃ OK (0x9000)
- ┃ ┣ OK ┠ALG_EC_SVDP_DH of local pubkey and remote privkey(unchanged point) ┃ SUCCESS ┃ 7 ms ┃ OK (0x9000)
- ┃ ┗ OK ┠ALG_EC_SVDP_DH of local pubkey and remote privkey(COMPRESSED point) ┃ SUCCESS ┃ 14 ms ┃ OK (0x9000)
- ┣ OK ┳ Test of the ALG_EC_SVDP_DHC KeyAgreement. ┃ SUCCESS ┃ All sub-tests had the expected result.
- ┃ ┣ OK ┠Allocated KeyAgreement(ALG_EC_SVDP_DHC) object ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000)
- ┃ ┣ OK ┠ALG_EC_SVDP_DHC of local pubkey and remote privkey(unchanged point) ┃ SUCCESS ┃ 3 ms ┃ OK (0x9000)
- ┃ ┗ OK ┠ALG_EC_SVDP_DHC of local pubkey and remote privkey(COMPRESSED point) ┃ SUCCESS ┃ 5 ms ┃ OK (0x9000)
- ┣ NOK ┠Allocated KeyAgreement(ALG_EC_SVDP_DH_PLAIN) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
- ┣ NOK ┠Allocated KeyAgreement(ALG_EC_SVDP_DHC_PLAIN) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
- ┣ NOK ┠Allocated KeyAgreement(ALG_EC_PACE_GM) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
- ┣ NOK ┠Allocated KeyAgreement(ALG_EC_SVDP_DH_PLAIN_XY) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
- ┣ OK ┳ Test of the ALG_ECDSA_SHA signature. ┃ SUCCESS ┃ All sub-tests had the expected result.
- ┃ ┣ OK ┠Allocated Signature(ALG_ECDSA_SHA) object ┃ SUCCESS ┃ 7 ms ┃ OK (0x9000)
- ┃ ┗ OK ┠ALG_ECDSA_SHA with local keypair(random data) ┃ SUCCESS ┃ 43 ms ┃ OK (0x9000)
- ┣ NOK ┠Allocated Signature(ALG_ECDSA_SHA_224) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
- ┣ NOK ┠Allocated Signature(ALG_ECDSA_SHA_256) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
- ┣ NOK ┠Allocated Signature(ALG_ECDSA_SHA_384) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
- ┗ NOK ┠Allocated Signature(ALG_ECDSA_SHA_512) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+ OK ┳ (0) Tests of 112b ALG_EC_FP support. ┃ SUCCESS ┃ All sub-tests matched the expected mask.
+ ┣ OK ┠Allocate both keypairs 112b ALG_EC_FP ┃ SUCCESS ┃ 22 ms ┃ OK (0x9000) OK (0x9000)
+ ┣ OK ┠Generate both keypairs ┃ SUCCESS ┃ 23 ms ┃ OK (0x9000) OK (0x9000)
+ ┣ OK ┠Allocate both keypairs 112b ALG_EC_FP ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000) OK (0x9000)
+ ┣ OK ┠Set custom curve parameters on both keypairs ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000) OK (0x9000)
+ ┣ OK ┠Generate both keypairs ┃ SUCCESS ┃ 8 ms ┃ OK (0x9000) OK (0x9000)
+ ┣ OK ┳ KeyAgreement tests. ┃ SUCCESS ┃ Some sub-tests did have the expected result.
+ ┃ ┣ OK ┳ Test of the ALG_EC_SVDP_DH KeyAgreement. ┃ SUCCESS ┃ Some ECDH is supported.
+ ┃ ┃ ┣ OK ┠Allocate KeyAgreement(ALG_EC_SVDP_DH) object ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000)
+ ┃ ┃ ┣ OK ┠ALG_EC_SVDP_DH of local pubkey and remote privkey(unchanged point) ┃ SUCCESS ┃ 2 ms ┃ OK (0x9000)
+ ┃ ┃ ┣ OK ┠ALG_EC_SVDP_DH of local pubkey and remote privkey(COMPRESSED point) ┃ SUCCESS ┃ 2 ms ┃ OK (0x9000)
+ ┃ ┃ ┗ OK ┠Mean = 1722885 ns, Median = 1718807 ns, Mode = 1614047 ns ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000)
+ ┃ ┣ OK ┳ Test of the ALG_EC_SVDP_DHC KeyAgreement. ┃ SUCCESS ┃ Some ECDH is supported.
+ ┃ ┃ ┣ OK ┠Allocate KeyAgreement(ALG_EC_SVDP_DHC) object ┃ SUCCESS ┃ 0 ms ┃ OK (0x9000)
+ ┃ ┃ ┣ OK ┠ALG_EC_SVDP_DHC of local pubkey and remote privkey(unchanged point) ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000)
+ ┃ ┃ ┣ OK ┠ALG_EC_SVDP_DHC of local pubkey and remote privkey(COMPRESSED point) ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000)
+ ┃ ┃ ┗ OK ┠Mean = 1563980 ns, Median = 1549170 ns, Mode = 1514747 ns ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000)
+ ┃ ┣ NOK ┠Allocate KeyAgreement(ALG_EC_SVDP_DH_PLAIN) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+ ┃ ┣ NOK ┠Allocate KeyAgreement(ALG_EC_SVDP_DHC_PLAIN) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+ ┃ ┣ NOK ┠Allocate KeyAgreement(ALG_EC_PACE_GM) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+ ┃ ┗ NOK ┠Allocate KeyAgreement(ALG_EC_SVDP_DH_PLAIN_XY) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+ ┗ OK ┳ Signature tests. ┃ SUCCESS ┃ Some sub-tests did have the expected result.
+ ┣ OK ┳ Test of the ALG_ECDSA_SHA signature. ┃ SUCCESS ┃ All sub-tests had the expected result.
+ ┃ ┣ OK ┠Allocate Signature(ALG_ECDSA_SHA) object ┃ SUCCESS ┃ 3 ms ┃ OK (0x9000)
+ ┃ ┣ OK ┠ALG_ECDSA_SHA with local keypair(random data) ┃ SUCCESS ┃ 14 ms ┃ OK (0x9000)
+ ┃ ┣ OK ┠Sign (Mean = 1890914 ns, Median = 1500125 ns, Mode = 1422588 ns) ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000)
+ ┃ ┗ OK ┠Verify (Mean = 1873952 ns, Median = 1870348 ns, Mode = 1843902 ns) ┃ SUCCESS ┃ 1 ms ┃ OK (0x9000)
+ ┣ NOK ┠Allocate Signature(ALG_ECDSA_SHA_224) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+ ┣ NOK ┠Allocate Signature(ALG_ECDSA_SHA_256) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+ ┣ NOK ┠Allocate Signature(ALG_ECDSA_SHA_384) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+ ┗ NOK ┠Allocate Signature(ALG_ECDSA_SHA_512) object ┃ FAILURE ┃ 0 ms ┃ fail (NO_SUCH_ALG, 0x0003)
+#### Legend
+ - Some general information about the test suite and card is output first, test data follows after.
+ - The **OK**/**NOK** values on the left represent the complete evaluated result of a test, as a test can be expected
+ to succeed or fail, this is different than the values on the right:
+ - **SUCCESS**: Is **OK**, the test was expected to pass and it did.
+ - **FAILURE**: Is **NOK**, the test was expected to pass, but it did not.
+ - **UXSUCCESS**: Is **NOK**, the test was expected to fail, but it did not.
+ - **XFAILURE**: Is **OK**, the test was expected to fail, and it did.
+ - **ERROR**: Is **NOK** an unexpected error during testing arose.
+ - The tests can be compounded into compound tests, which are visible as a tree of tests and sub-tests.
+ - The duration of non-compound tests is shown in the third column, this is a rough estimate, measured from before the APDU is sent, to just after the response is received.
+ - The cause of the test result, is shown in the last column, for non-compound tests, these are JavaCard(or custom) status words, from operations done on the card.
If you are interested in testing support for other JavaCard algorithms, please visit JCAlgTester project: https://github.com/crocs-muni/JCAlgTest
@@ -181,54 +221,97 @@ If you are interested in testing support for other JavaCard algorithms, please v
Currently supported libraries include:
- BouncyCastle
- SunEC
+ - OpenSSL
+ - Crypto++
- libtomcrypt
- botan
+ - Microsoft CNG
+For more information on ECC libraries see [LIBS](docs/LIBS.md).
-```
-usage: ECTesterStandalone.jar [-V] [-h] [ (ecdh [-t <type>] [-n <amount>] [-b <n>] [-nc <cat/id>]) |
-(ecdsa [-t <type>] [-n <amount>] [-b <n>] [-nc <cat/id>] [-f <file>]) |
-(export [-t <type>] [-b <n>]) | (generate [-nc <cat/id>] [-n <amount>] [-t
-<type>] [-b <n>]) | (list-data [what]) | (list-libs) | (test [-gt <type>]
-[-kt <type>] [-st <type>] [-b <n>] [-nc <cat/id>]) ] [lib]
+### Setup
+
+OpenJDK JRE is required to test ECDH on Windows properly, as Oracle JRE requires the Java Cryptography Providers
+for certain classes (such as a [KeyAgreement](https://docs.oracle.com/javase/8/docs/api/javax/crypto/KeyAgreement.html))
+to be signed by keys that are signed by their JCA Code Signing Authority. ECTester internally uses Java Cryptography Provider
+API to expose and test native libraries. OpenJDK for Windows can be obtained from [ojdkbuild/ojdkbuild](https://github.com/ojdkbuild/ojdkbuild).
+
+Installing the Java Cryptography Extension Unlimited Strength policy files is necessary to do testing
+with quite a lot of practical key sizes, they are available for download:
- -V,--version Print version info.
- -h,--help Print help.
- [lib] What library to use.
+ - [Java 6](http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html)
+ - [Java 7](http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html)
+ - [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html)
- ecdh:
+To install, place them in `${java.home}/jre/lib/security/`.
+
+### Options
+
+```
+usage: ECTesterStandalone.jar [-V] [-h] [-C]
+ [ (ecdh [-b <n>] [-nc <cat/id>] [-cn <name>] [-t <type>] [--key-type <algorithm>] [-n <amount>]) |
+ (ecdsa [-b <n>] [-nc <cat/id>] [-cn <name>] [-t <type>] [-n <amount>] [-f <file>]) |
+ (export [-b <n>] [-t <type>]) |
+ (generate [-b <n>] [-nc <cat/id>] [-cn <name>] [-n <amount>] [-t <type>]) |
+ (list-data [what]) |
+ (list-libs) |
+ (list-suites) |
+ (test [-b <n>] [-nc <cat/id>] [-cn <name>] [-gt <type>] [-kt <type>] [-st <type>] [-f <format>] [--key-type <algorithm>]
+ <test-suite>) ]
+ [lib]
+
+ ecdh: | Perform EC based KeyAgreement. |
+ -b,--bits <n> What size of curve to use.
+ -nc,--named-curve <cat/id> Use a named curve, from CurveDB: <cat/id>
+ -cn,--curve-name <name> Use a named curve, search from curves
+ supported by the library: <name>
-t,--type <type> Set KeyAgreement object [type].
+ --key-type <algorithm> Set the key [algorithm] for which the key
+ should be derived in KeyAgreements with
+ KDF. Default is "AES".
-n,--amount <amount> Do ECDH [amount] times.
+
+ ecdsa: | Perform EC based Signature. |
-b,--bits <n> What size of curve to use.
-nc,--named-curve <cat/id> Use a named curve, from CurveDB: <cat/id>
-
- ecdsa:
+ -cn,--curve-name <name> Use a named curve, search from curves
+ supported by the library: <name>
-t,--type <type> Set Signature object [type].
-n,--amount <amount> Do ECDSA [amount] times.
- -b,--bits <n> What size of curve to use.
- -nc,--named-curve <cat/id> Use a named curve, from CurveDB: <cat/id>
-f,--file <file> Input [file] to sign.
- export:
- -t,--type <type> Set KeyPair object [type].
- -b,--bits <n> What size of curve to use.
+ export: | Export default curve parameters. |
+ -b,--bits <n> What size of curve to use.
+ -t,--type <type> Set KeyPair object [type].
- generate:
+ generate: | Generate EC keypairs. |
+ -b,--bits <n> What size of curve to use.
-nc,--named-curve <cat/id> Use a named curve, from CurveDB: <cat/id>
+ -cn,--curve-name <name> Use a named curve, search from curves
+ supported by the library: <name>
-n,--amount <amount> Generate [amount] of EC keys.
-t,--type <type> Set KeyPairGenerator object [type].
- -b,--bits <n> What size of curve to use.
- list-data:
- [what] what to list.
+ list-data: | List/show contained EC domain parameters/keys. |
+ [what] what to list.
- list-libs:
+ list-libs: | List supported libraries. |
- test:
+ list-suites: | List supported test suites. |
+
+ test: | Test a library. |
+ -b,--bits <n> What size of curve to use.
+ -nc,--named-curve <cat/id> Use a named curve, from CurveDB: <cat/id>
+ -cn,--curve-name <name> Use a named curve, search from curves
+ supported by the library: <name>
-gt,--kpg-type <type> Set the KeyPairGenerator object [type].
-kt,--ka-type <type> Set the KeyAgreement object [type].
-st,--sig-type <type> Set the Signature object [type].
- -b,--bits <n> What size of curve to use.
- -nc,--named-curve <cat/id> Use a named curve, from CurveDB: <cat/id>
+ -f,--format <format> Set the output format, one of
+ text,yaml,xml.
+ --key-type <algorithm> Set the key [algorithm] for which the key
+ should be derived in KeyAgreements with
+ KDF. Default is "AES".
+ <test-suite> The test suite to run.
+```
-``` \ No newline at end of file
diff --git a/applet/gppro_upload.bat b/applet/gppro_upload.bat
index cbfd5ae..0b31b1e 100644
--- a/applet/gppro_upload.bat
+++ b/applet/gppro_upload.bat
@@ -1,6 +1,7 @@
-gp.exe -delete 4543546573746572 -deletedeps -verbose
-gp.exe -deletedeps -verbose -delete 4A43416C6754657374
+gp.exe -deletedeps -verbose -delete 4C6162616B417070
+gp.exe -deletedeps -verbose -delete 4A43416C6754657374
+gp.exe -deletedeps -verbose -delete 4543546573746572
-gp.exe -install ectester.cap -verbose
+gp.exe -install ectester.cap -verbose -d
diff --git a/applet/gppro_upload.sh b/applet/gppro_upload.sh
index a94a948..da971af 100755
--- a/applet/gppro_upload.sh
+++ b/applet/gppro_upload.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-java -jar gp.jar -delete 4543546573746572 -deletedeps -verbose
+java -jar gp.jar -deletedeps -verbose -delete 4C6162616B417070
java -jar gp.jar -deletedeps -verbose -delete 4A43416C6754657374
+java -jar gp.jar -deletedeps -verbose -delete 4543546573746572
-java -jar gp.jar -install ectester.cap -verbose
+java -jar gp.jar -install ectester.cap -verbose -d
diff --git a/applet/gppro_upload_emv.bat b/applet/gppro_upload_emv.bat
index 737f8ac..1f2f397 100644
--- a/applet/gppro_upload_emv.bat
+++ b/applet/gppro_upload_emv.bat
@@ -2,7 +2,6 @@ gp.exe -deletedeps -verbose -emv -delete 4C6162616B417070
gp.exe -deletedeps -verbose -emv -delete 4A43416C6754657374
gp.exe -deletedeps -verbose -emv -delete 4543546573746572
-
gp.exe -install ectester.cap -verbose -emv -d
diff --git a/applet/gppro_upload_emv.sh b/applet/gppro_upload_emv.sh
index c3b42b1..8317833 100755
--- a/applet/gppro_upload_emv.sh
+++ b/applet/gppro_upload_emv.sh
@@ -3,7 +3,6 @@ java -jar gp.jar --deletedeps --verbose -emv --delete 4C6162616B417070
java -jar gp.jar --deletedeps --verbose -emv --delete 4A43416C6754657374
java -jar gp.jar --deletedeps --verbose -emv --delete 4543546573746572
-
java -jar gp.jar --install ectester.cap --verbose --emv -d
diff --git a/build-applet.xml b/build-applet.xml
index 9d7d4d6..f8f15e2 100644
--- a/build-applet.xml
+++ b/build-applet.xml
@@ -2,11 +2,14 @@
<project basedir="." default="build" name="ECTesterApplet">
<!-- Based on Martin Paljak's applets playground -->
<!-- Applet building dependencies -->
- <property name="JC222" value="ext/java_card_kit-2_2_2"/>
- <property name="JC221" value="ext/java_card_kit-2_2_1"/>
- <property name="JC303" value="ext/java_card_kit-3_0_3"/>
- <property name="OP20" value="ext/visa_openplatform-2_0"/>
- <property name="GP211" value="ext/globalplatform-2_1_1"/>
+ <property name="SDK_PATH" value="ext/sdks"/>
+
+ <property name="JC212" value="${SDK_PATH}/jc212_kit"/>
+ <property name="JC221" value="${SDK_PATH}/jc221_kit"/>
+ <property name="JC222" value="${SDK_PATH}/jc222_kit"/>
+ <property name="JC303" value="${SDK_PATH}/jc303_kit"/>
+ <property name="JC304" value="${SDK_PATH}/jc304_kit"/>
+ <property name="JC305u1" value="${SDK_PATH}/jc305u1_kit"/>
<!-- ant-javacard task from javacard.pro -->
<taskdef name="javacard" classname="pro.javacard.ant.JavaCard" classpath="ext/ant-javacard.jar"/>
@@ -29,4 +32,8 @@
<exec dir="applet" executable="./gppro_upload_emv.sh" osfamily="unix"/>
<exec dir="applet" executable="./gppro_upload_emv.bat" osfamily="windows"/>
</target>
+
+ <target name="clean" description="Clean the built CAP file.">
+ <delete file="applet/ectester.cap" quiet="true"/>
+ </target>
</project>
diff --git a/build-standalone.xml b/build-standalone.xml
index dcfb1f3..685f791 100644
--- a/build-standalone.xml
+++ b/build-standalone.xml
@@ -80,15 +80,31 @@
<antcall target="dist-build.package"/>
</target>
+ <target name="sign" depends="package">
+ <signjar keystore="nbproject/keystore" alias="ectester" storepass="ectester">
+ <path>
+ <fileset dir="dist" includes="*.jar"/>
+ </path>
+ </signjar>
+ </target>
+
<target name="libs-try">
<exec dir="src/cz/crcs/ectester/standalone/libs/jni" executable="make" osfamily="unix">
<arg value="-k"/>
</exec>
+ <exec dir="src/cz/crcs/ectester/standalone/libs/jni" executable="cmd" osfamily="windows">
+ <arg value="/c"/>
+ <arg value="Makefile.bat"/>
+ </exec>
</target>
<target name="libs">
<exec dir="src/cz/crcs/ectester/standalone/libs/jni" failonerror="true" executable="make" osfamily="unix">
<arg value="-k"/>
</exec>
+ <exec dir="src/cz/crcs/ectester/standalone/libs/jni" failonerror="true" executable="cmd" osfamily="windows">
+ <arg value="/c"/>
+ <arg value="Makefile.bat"/>
+ </exec>
</target>
<target name="-post-compile" depends="libs-try"/>
@@ -97,6 +113,11 @@
osfamily="unix">
<arg value="clean"/>
</exec>
+ <exec dir="src/cz/crcs/ectester/standalone/libs/jni" failonerror="true" executable="cmd" osfamily="windows">
+ <arg value="/c"/>
+ <arg value="Makefile.bat"/>
+ <arg value="clean"/>
+ </exec>
</target>
<target name="headers" depends="compile">
@@ -115,6 +136,27 @@
<class name="cz.crcs.ectester.standalone.libs.jni.NativeECPrivateKey$Botan"/>
<class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$Botan"/>
<class name="cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$Botan"/>
+ <class name="cz.crcs.ectester.standalone.libs.CryptoppLib"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeProvider$Cryptopp"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$Cryptopp"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeECPublicKey$Cryptopp"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeECPrivateKey$Cryptopp"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$Cryptopp"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$Cryptopp"/>
+ <class name="cz.crcs.ectester.standalone.libs.OpensslLib"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeProvider$Openssl"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$Openssl"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeECPublicKey$Openssl"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeECPrivateKey$Openssl"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$Openssl"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$Openssl"/>
+ <class name="cz.crcs.ectester.standalone.libs.MscngLib"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeProvider$Mscng"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$Mscng"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeECPublicKey$Mscng"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeECPrivateKey$Mscng"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$Mscng"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$Mscng"/>
</javah>
</target>
</project>
diff --git a/docs/CURVES.md b/docs/CURVES.md
index 4a80d49..a417035 100644
--- a/docs/CURVES.md
+++ b/docs/CURVES.md
@@ -1,47 +1,95 @@
# Curves
+ECTester contains a collection of elliptic curve/point parameters, these parameters either come from standards or
+were generated manually or using [ecgen](https://github.com/J08nY/ecgen).
-## SECG
+These parameters can be found in the [cz.crcs.ectester.data](/src/cz/ectester/data/) package.
+
+
+## Standard
+
+### SECG
SEC 2: Recommended Elliptic Curve Domain Parameters version 2.0 January 27, 2010
[Source](http://www.secg.org/sec2-v2.pdf)
-## NIST
+### NIST
RECOMMENDED ELLIPTIC CURVES FOR FEDERAL GOVERNMENT USE July 1999
[Source](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf)
-## x962
+### x962
ANSI X9.62 example curves.
-## Brainpool
+### Brainpool
ECC Brainpool Standard Curves and Curve Generation v. 1.0 19.10.2005
[Source](http://www.ecc-brainpool.org/download/Domain-parameters.pdf)
-## anssi
+### anssi
Agence nationale de la sécurité des systèmes d'information: Publication d'un paramétrage de courbe elliptique visant des applications de passeport électronique et de l'administration électronique française. 21 November 2011
-## GOST
+### GOST
GOST R 34.10-2001: RFC5832 curves.
[Source](https://tools.ietf.org/html/rfc5832)
-## anomalous
+### Barreto-Naehrig
+Barreto-Naehrig curves from: A Family of Implementation-Friendly BN Elliptic Curves
+
+[Source](https://eprint.iacr.org/2010/429.pdf)
+
+### Other
+An assortment of some other curves.
+Montgomery curves transformed into short Weierstrass form from <https://eprint.iacr.org/2013/647.pdf>
+
+Curve25519 transformed into short Weierstrass form.
+
+
+## Generated
+
+### anomalous
These prime field curves have the same order as the field order, and are susceptible to attacks reducing ECDLP over a multiplicative group of the curve, to DLP over an additive group of the underlying field, which is easy (linear time).
Some of these are from Atsuko Miyaji's [paper](https://dspace.jaist.ac.jp/dspace/bitstream/10119/4464/1/73-61.pdf), others were generated using [ecgen](htps://github.com/J08nY/ecgen).
-## invalid
+### invalid
This category contains pre-generated invalid curves for a large subset of NIST, SECG and Brainpool curves. Invalid curves for a given curve, are short Weierstrass curves with all parameters equal to the given curve except the `b` parameter. These curves can be used to [attack some implementations](https://www.nds.rub.de/media/nds/veroeffentlichungen/2015/09/14/main-full.pdf).
-Generated using [ecgen](https://github.com/J08nY/ecgen)
+Generated using [ecgen](https://github.com/J08nY/ecgen).
-## composite
+### composite
Contains curves of composite order, with small order points.
-Generated using [ecgen](https://github.com/J08nY/ecgen)
+Generated using [ecgen](https://github.com/J08nY/ecgen).
+
+### wrong
+Contains parameters that are not elliptic curves(over Fp and F2m), such as `p` parameter that is not prime or an irreducible polynomial that is not irreducible.
+
+Generated manually.
+
+### twist
+Contains pre-generated points on twists of known named curves from NIST, SECG.
+These points can be used to attack some implementations.
+
+Generated using [ecgen](https://github.com/J08nY/ecgen).
+
+### degenerate
+Contains pre-generated points on the line `Y: x = 0`. These points are constructed from elements of prime
+order in the multiplicative group F_p given a curve over it.
+
+Generate manually using [PARI/GP](http://pari.math.u-bordeaux.fr/).
+
+### cofactor
+Contains curves that are composite order, with points not on the subgroup generated by the generator.
+
+Generated using [ecgen](https://github.com/J08nY/ecgen).
+
+### supersingular
+Contains supersingular curves, over F_p with order equal to p + 1. These have embedding degree equal to 2.
+
+Generated using [ecgen](https://github.com/J08nY/ecgen).
-## wrong
-Contains parameters that are not elliptic curves(over Fp and F2m), such as `p` parameter that is not prime, irreducible polynomial that is not irreducible and similar.
+## Other
-Generated manually. \ No newline at end of file
+### Wycheproof
+Contains some test vectors from the [google/Wycheproof](https://github.com/google/wycheproof) project. \ No newline at end of file
diff --git a/docs/FORMAT.md b/docs/FORMAT.md
index 849a62c..bde2543 100644
--- a/docs/FORMAT.md
+++ b/docs/FORMAT.md
@@ -56,4 +56,8 @@ Output of the `-dsa/--ecdsa` option.
## Test runs
By default test runs are output in a human readable format, however YAML and XML is also supported and can be selected
-by using the `-o/--output` option.
+by using the `--format` option. Also, prefixing the output file name when using the `-o/--output` option allows to output
+the same test run in different formats to different files.
+
+For example:
+`--format yaml -o default_output.yaml -o xml:output_file.xml -o text:readable_text_file.txt `
diff --git a/docs/IMPLEMENTATIONS.md b/docs/IMPLEMENTATIONS.md
new file mode 100644
index 0000000..b4a4ea8
--- /dev/null
+++ b/docs/IMPLEMENTATIONS.md
@@ -0,0 +1,552 @@
+# Implementations
+
+This document contains information about possible implementation choices and algorithms when implementing elliptic curve cryptography. It is mainly concerned with curve models, coordinate systems, addition formulas and scalar multiplication algorithms. Also, only curves over \( \mathbb{F}_p \) are analyzed.
+
+---
+
+## Curve models
+
+### Weierstrass (full)
+
+#### Affine
+$$ y^2 + a_1xy + a_3y = x^3 + a_2x^2 + a_4x + a_6 $$
+
+#### Projective
+$$ Y^2Z + a_1XYZ + a_3YZ^2 = X^3 + a_2X^2Z + a_4XZ^2 + a_6Z^3 $$
+
+
+### Weierstrass (short)
+
+[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html)
+
+ toweierstrass weierx = x
+ toweierstrass weiery = y
+ a0 = 1
+ a1 = 0
+ a2 = 0
+ a3 = 0
+ a4 = a
+ a6 = b
+ fromweierstrass x = weierx
+ fromweierstrass y = weiery
+
+#### Affine
+$$ y^2 = x^3 + a x + b $$
+
+#### Projective
+$$ Y^2Z = X^3 + aXZ^2 + bZ^3 $$
+
+#### Jacobian
+$$ Y^2 = X^3 + aXZ^4 + bZ^6 $$
+
+
+### Montgomery
+
+[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-montgom.html)
+
+ toweierstrass weierx = x
+ toweierstrass weiery = y
+ a0 = b
+ a1 = 0
+ a2 = a
+ a3 = 0
+ a4 = 1
+ a6 = 0
+ fromweierstrass x = weierx
+ fromweierstrass y = weiery
+
+#### Affine
+$$ By^2 = x^3 + Ax^2 + x $$
+
+
+### Edwards
+
+[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-edwards.html)
+
+ toweierstrass u = (c+y)/(c-y)
+ toweierstrass v = 2 c (c+y)/(x(c-y))
+ a0 = 1/(1-d c^4)
+ a1 = 0
+ a2 = 4/(1-d c^4)-2
+ a3 = 0
+ a4 = 1
+ a6 = 0
+ fromweierstrass x = 2 c u/v
+ fromweierstrass y = c(u-1)/(u+1)
+
+#### Affine
+$$ x^2 + y^2 = c^2 (1 + dx^2y^2) $$
+
+
+### Twisted Edwards
+
+[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-twisted.html)
+
+ toweierstrass u = (1+y)/(1-y)
+ toweierstrass v = 2 (1+y)/(x(1-y))
+ a0 = 1/(a-d)
+ a1 = 0
+ a2 = 4 a/(a-d)-2
+ a3 = 0
+ a4 = 1
+ a6 = 0
+ fromweierstrass x = 2 u/v
+ fromweierstrass y = (u-1)/(u+1)
+
+#### Affine
+$$ ax^2 + y^2=1 + dx^2y^2 $$
+
+
+### Hessian
+
+[EFD entry](https://www.hyperelliptic.org/EFD/g1p/auto-hessian.html)
+
+ toweierstrass u = 12(d^3-1)/(d+x+y)-9 d^2
+ toweierstrass v = 36(y-x)(d^3-1)/(d+x+y)
+ a0 = 1
+ a1 = 0
+ a2 = 0
+ a3 = 0
+ a4 = -27 d(d^3+8)
+ a6 = 54(d^6-20 d^3-8)
+ fromweierstrass x = (36(d^3-1)-v)/(6(u+9 d^2))-d/2
+ fromweierstrass y = (v+36(d^3-1))/(6(u+9 d^2))-d/2
+
+#### Affine
+$$ x^3+y^3+1=3dxy $$
+
+#### Projective
+$$ X^3 + Y^3 + Z^3 = 3dXYZ $$
+
+
+---
+
+## Coordinates
+
+### Affine
+
+$$ [x, y] \in \mathbb{K}^2 $$
+
+*(Weierstrass)* infinity is special cased, sometimes represented as \( [0] \).
+
+*(Weierstrass)* negation: \(-[x, y] = [x, -y] \)
+
+ - To Projective: \( [x, y] \rightarrow (x : y : 1) \)
+ - To Jacobian: \( [x, y] \rightarrow (x : y : 1) \)
+ - To Chudnovsky: \( [x, y] \rightarrow (x : y : 1 : 1 : 1) \)
+
+### Projective
+\begin{align*}
+[X, Y, Z] &\in \mathbb{K}^3 \\
+[X_1, Y_1, Z_1] &\sim [X_2, Y_2, Z_2] \\
+\text{if}\ X_1 &= λ X_2, \\
+ Y_1 &= λ Y_2, \\
+ Z_1 &= λ Z_2 \\
+\text{for some}\ λ &\in \mathbb{K}^* \\
+(X : Y : Z) &= \{(λ X, λ Y, λ Z) | λ \in \mathbb{K}^* \}
+\end{align*}
+
+*(Weierstrass)* infinity is \((0 : 1 : 0)\).
+
+*(Weierstrass)* negation: \( -(X : Y : Z) = (X : -Y : Z) \)
+
+ - To Affine: \( (X : Y : Z) \rightarrow [X/Z, Y/Z] \)
+ - To Jacobian: \( (X : Y : Z) \rightarrow (X/Z : Y/Z : 1) \) ?
+ - To Chudnovsky: \( (X : Y : Z) \rightarrow (X/Z : Y/Z : 1 : 1 : 1) \) ?
+
+### Jacobian
+\begin{align*}
+[X, Y, Z] &\in \mathbb{K}^3 \\
+[X_1, Y_1, Z_1] &\sim [X_2, Y_2, Z_2] \\
+\text{if}\ X_1 &= λ^2 X_2, \\
+ Y_1 &= λ^3 Y_2, \\
+ Z_1 &= λ Z_2 \\
+\text{for some}\ λ &\in \mathbb{K}^* \\
+(X : Y : Z) &= \{(λ^2 X, λ^3 Y, λ Z) | λ \in \mathbb{K}^* \}
+\end{align*}
+
+*(Weierstrass)* infinity is \( (1 : 1 : 0) \).
+
+*(Weierstrass)* negation: \( -(X : Y : Z) = (X : -Y : Z) \)
+
+ - To Affine: \( (X : Y : Z) \rightarrow [X/Z^2, Y/Z^3] \)
+ - To Projective: \( (X : Y : Z) \rightarrow (X/Z^2 : Y/Z^3 : 1) \) ?
+ - To Chudnovsky: \( (X : Y : Z) \rightarrow (X : Y : Z : Z^2 : Z^3) \)
+
+### Chudnovsky
+\begin{align*}
+[X, Y, Z, Z^2, Z^3] &\in \mathbb{K}^5 \\
+(X : Y : Z : Z^2 : Z^3 ) &= \{(λ^2 X, λ^3 Y, λ Z, λ^2 Z^2, λ^3 Z^3) | λ \in \mathbb{K}^* \}
+\end{align*}
+
+*(Weierstrass)* infinity is \( (1 : 1 : 0 : 0 : 0) \). ?
+
+*(Weierstrass)* negation: \( -(X : Y : Z : Z^2 : Z^3) = (X : -Y : Z : Z^2 : Z^3) \)
+
+ - To Affine: \( (X : Y : Z : Z^2 : Z^3) \rightarrow [X/Z^2, Y/Z^3] \)
+ - To Projective: \( (X : Y : Z : Z^2 : Z^3) \rightarrow (X/Z^2 : Y/Z^3 : 1) \) ?
+ - To Jacobian: \( (X : Y : Z : Z^2 : Z^3) \rightarrow (X : Y : Z) \)
+
+
+---
+
+## Formulas
+
+ - Addition
+ - Doubling
+ - Tripling
+ - Differential addition
+ - Differential addition and doubling
+ - Scaling
+
+See EFD[^3].
+
+---
+
+## Scalar multiplication
+
+See TAOCP volume 2, section 4.6.3 for introduction to multiplication/exponentiation and addition/multiplication chains.[^5]
+
+Scalar multiplication on elliptic curves is very similar to usual multiplication/exponentiation in general additive/multiplicative groups, respectively, with some additional structure:
+
+ - \(A + B\) when \(A \ne B\) might be a different operation from \(A + A = [2]A\), and also sometimes takes different time.
+ - negation \(-A\) is easy/fast.
+ - \(0\) sometimes has a special representation and thus requires special casing.
+ - sometimes, there exists a fast operation of \(\phi: E(\mathbb{F}_p) \rightarrow E(\mathbb{F}_p) \) with \( \phi(P) = [k]P \) for some \(k \in \mathbb{K}\) computable using some endomorphism on the curve.
+
+Some links:
+
+ - [wiki/Addition_chain](https://en.wikipedia.org/wiki/Addition_chain)
+ - [wiki/Addition-subtraction_chain](https://en.wikipedia.org/wiki/Addition-subtraction_chain)
+ - [wiki/Exponentiation_by_squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring)
+ - [wiki/Addition-chain_exponentiation](https://en.wikipedia.org/wiki/Addition-chain_exponentiation)
+
+We define:
+
+ - \( \lambda(k) = \lfloor \log_2 k \rfloor \) , the size of k
+ - \( k_i \) , the *i*-th bit of *k*
+ - \( \nu(k) = \vert \{ i \vert 0 \le i \le \lambda(k), k_i = 1\} \vert \) , the number of nonzero bits in *k*
+ - \( l(k) \) , the length of NAF of *k*
+ - \( \sigma(k) = \vert \{ i \vert 0 \le i \le l(k), NAF(k)_i \ne 0 \} \vert \) , the number of nonzero values in the NAF of *k*
+ - \( C_2 \) , the cost of doubling a point
+ - \( C_+ \) , the cost of point addition
+ - \( C_{algo}(k) \) , the cost of scalar multiplication by *k* of the algorithm *algo*
+ - *Addition chain* of *n*, is a sequence of integers:
+\( 1 = a_0, a_1, \ldots, a_r = n\),
+where \(a_i = a_j + a_k\) for some \( k \le j < i, \forall i \in \{ 1, 2, \ldots, r \} \)
+ - *Addition-subtraction chain* of *n*, is a sequence of integers:
+\( 1 = a_0, a_1, \ldots, a_r = n\),
+where \(a_i = \pm a_j \pm a_k\) for some \( k \le j < i, \forall i \in \{ 1, 2, \ldots, r \} \)
+ - *Addition sequence* for \( r_1, r_2, \ldots, r_t \) is an addition chain: \( 1 = a_1, a_2, \ldots, a_l \) which contains \( r_1, r_2, \ldots, r_t \). Useful when operating with one element and many powers \( g^{r_1}, g^{r_2}, \ldots \)
+ - *Vector addition chain* for \(r \in \mathbb{N}^t \) is a sequence of elements \( v_i \) of \( \mathbb{N}^t \) such that \( v_i = e_i \) for \( 1 \le i \le t \) and \( v_i = v_j + v_k \) for \(j \le k < i \). Useful when powering many elements to many powers \( g_1^{r_1}, g_2^{r_2}, \ldots \)
+
+### Double and Add (binary exponentiation)
+
+Uses binary addition chain.
+
+<u>Algorithm 3.26</u> (right-to-left) in GECC[^1]
+
+ INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q).
+ OUTPUT: [k]P.
+ 1. Q ↠∞.
+ 2. For i from t - 1 downto 0 do
+ 2.1 If k_i = 1 then Q ↠Q + P.
+ 2.2 P ↠2P.
+ 3. Return(Q).
+
+<u>Algorithm 3.27</u> (left-to-right) in GECC[^1]
+
+ INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q).
+ OUTPUT: [k]P.
+ 1. Q ↠∞.
+ 2. For i from t - 1 downto 0 do
+ 2.1 Q ↠2Q.
+ 2.2 If k_i = 1 then Q ↠Q + P.
+ 3. Return(Q).
+
+Cost: \( C_{binexp}(k) = \lambda(k)C_2 + (\nu(k) - k_0)C_+\)[^7]
+
+### Double and Add Always (binary exponentiation - constant time)
+
+Uses binary addition chain, but does all the additions/multiplications.
+
+(right-to-left)
+
+ INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q).
+ OUTPUT: [k]P.
+ 1. Q ↠∞.
+ 2. For i from t - 1 downto 0 do
+ 2.1 If k_i = 1 then Q ↠Q + P else Dummy ↠Q + P.
+ 2.2 P ↠2P.
+ 3. Return(Q).
+
+(left-to-right)
+
+ INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q).
+ OUTPUT: [k]P.
+ 1. Q ↠∞.
+ 2. For i from t - 1 downto 0 do
+ 2.1 Q ↠2Q.
+ 2.2 If k_i = 1 then Q ↠Q + P else Dummy ↠Q + P.
+ 3. Return(Q).
+
+Cost: \( C_{const\_binexp}(k) = \lambda(k) (C_2 + C_+) \) ?
+
+
+### Binary NAF multiplication (signed binary exponentiation)
+
+**Definition 3.28**[^1] A *non-adjacent form (NAF)* of a positive integer *k* is an expression \( k = \Sigma_{i=0}^{l - 1} k_i 2^i \) where \(k_i \in \{0, ±1\}, k_{l−1} \ne 0\), and no two consecutive digits \( k_i \) are nonzero. The length of the NAF is *l*.
+
+<u>Algorithm 3.30</u> Computing the NAF of a positive integer[^1]
+
+ INPUT: A positive integer k.
+ OUTPUT: NAF(k).
+ 1. i ↠0.
+ 2. While k ≥ 1 do
+ 2.1 If k is odd then:
+ k_i ↠2 − (k mod 4), k ↠k − k_i ;
+ 2.2 Else:
+ k_i ↠0.
+ 2.3 k ↠k/2, i ↠i + 1.
+ 3. Return(k_{i−1}, k_{i−2}, ..., k_1, k_0).
+
+<u>Algorithm 3.31</u> Binary NAF multiplication (left-to-right)[^1]
+
+ INPUT: Positive integer k, P ∈ E(F_q).
+ OUTPUT: [k]P.
+ 1. Use Algorithm 3.30 to compute NAF(k).
+ 2. Q ↠∞.
+ 3. For i from l - 1 downto 0 do
+ 3.1 Q ↠2Q.
+ 3.2 If k_i = 1 then Q ↠Q + P.
+ 3.3 If k_i = -1 then Q ↠Q - P.
+ 4. Return(Q).
+
+Can be made constant time.
+
+Cost: \( C_{bin\_NAF} = l(k)C_2 + \sigma(k)C_+ + \text{NAF computation cost}\) ?
+
+### \(m\)-ary method
+
+Like binary double-and-add but uses a different base *m*.[^6]
+
+ INPUT: k = (k_{t-1}, ..., k_1, k_0)_m, P ∈ E(F_q).
+ OUTPUT: [k]P
+ 1. Compute P_i = [i]P for i ∈ {1, 2, ..., m - 1}.
+ 2. Q ↠∞.
+ 3. For i from l downto 0 do
+ 3.1 Q ↠[m]Q.
+ 3.2 Q ↠Q + P_{k_i}.
+ 4. Return(Q).
+
+### \( 2^r \) method
+
+Like \(m\)-ary method, with \( m = 2^r \), means that `[m]Q` is doable with only doubling.[^6]
+
+### Sliding window
+
+<u>Algorithm 13.6</u> Sliding window in HEHCC[^2]
+
+ INPUT: Window width w, k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q).
+ OUTPUT: [k]P
+ 1. Compute P_i = [i]P for i ∈ {3, 5, ..., 2^w - 1}. //precomputation for fixed P
+ 2. Q ↠∞, i ↠t - 1.
+ 3. While i ≥ 0 do
+ 3.1 If k_i = 0 then:
+ Q ↠[2]Q, i ↠i - 1.
+ 3.2 Else:
+ 3.2.1 s ↠max(i - k + 1, 0).
+ 3.2.2 While k_s = 0 do
+ s ↠s + 1.
+ 3.2.3 For h from 1 to i - s + 1 do
+ Q ↠[2]Q.
+ 3.2.4 u ↠(k_i, ..., k_s)_2.
+ 3.2.5 Q ↠P_u. // u is odd.
+ 3.2.6 i ↠s - 1.
+ 4. Return(Q).
+
+<u>Algorithm 3.38</u> Sliding window with NAF(signed sliding window) in GECC[^1]
+
+ INPUT: Window width w, positive integer k, P ∈ E(F_q).
+ OUTPUT: [k]P.
+ 1. Use Algorithm 3.30 to compute NAF(k).
+ 2. Compute P_i = [i]P for i ∈ {1, 3, ..., 2(2^w - (-1)^w)/3 - 1}. //precomputation for fixed P
+ 3. Q ↠∞, i ↠l - 1.
+ 4. While i ≥ 0 do
+ 4.1 If k_i = 0 then:
+ t ↠1, u ↠0.
+ 4.2 Else:
+ find the largest t ≤ w such that u ↠(k_i , ..., k_{i-t+1}) is odd.
+ 4.3 Q ↠[2^t]Q.
+ 4.4 If u > 0 then:
+ Q ↠Q + P_u.
+ 4.5 Else:
+ if u < 0 then Q ↠Q - P_{-u}.
+ 4.6 i ↠i - t.
+ 5. Return(Q).
+
+### Window NAF multiplication
+
+**Definition 3.32**[^1] Let \( w \ge 2 \) be a positive integer. A *width-w NAF* of a positive integer *k* is an expression \( k = \Sigma_{i=0}^{l - 1} k_i 2^i \) where each nonzero coefficient \( k_i \) is odd, \( \vert k_i \vert < 2^{w - 1}, k_{l-1} \ne 0 \), and at most one of any *w* consecutive digits is nonzero. The length of the width-w NAF is *l*.
+
+
+<u>Algorithm 3.35</u> Computing the width-w NAF of a positive integer[^1]
+
+ INPUT : Window width w, positive integer k.
+ OUTPUT : NAF-w(k).
+ 1. i ↠0.
+ 2. While k ≥ 1 do
+ 2.1 If k is odd then:
+ k_i ↠k mods 2^w , k ↠k − k_i; // k mods 2^w is an integer u, -2^{w-1} ≤ u < 2^{w-1}, u ≡ k mod 2^w
+ 2.2 Else:
+ k_i ↠0.
+ 2.3 k ↠k/2, i ↠i + 1.
+ 3. Return(k_{i−1}, k_{i−2}, ..., k_1, k_0).
+
+<u>Algorithm 3.36</u> in GECC[^1]
+
+ INPUT: Window width w, positive integer k, P ∈ E(F_q).
+ OUTPUT: [k]P.
+ 1. Use Algorithm 3.35 to compute NAF-w(k).
+ 2. Compute P_i = [i]P for i ∈ {1, 3, 5, ..., 2^{w-1} - 1}. //precomputation for fixed P
+ 3. Q ↠∞.
+ 4. For i from l - 1 downto 0 do
+ 4.1 Q ↠2Q.
+ 4.2 If k_i != 0 then:
+ If k_i > 0 then:
+ Q ↠Q + P_{k_i} ;
+ Else:
+ Q ↠Q - P_{-k_i} .
+ 5. Return(Q).
+
+### Fractional window
+
+[^10] and [^11]
+
+### Montgomery ladder
+
+The same name, Montgomery ladder, is used both for the general ladder idea of exponentiation/scalar-multiplication and the concrete *x*-coordinate only addition formulas and scalar multiplication algorithm on Montgomery curves.
+
+<u>Algorithm 13.35</u> in [^2] (general Montgomery ladder)
+
+ INPUT: k = (k_{t-1}, ..., k_1, k_0)_2, P ∈ E(F_q).
+ OUTPUT: [k]P .
+ 1. P_1 ↠P and P_2 ↠[2]P
+ 2. For i = t − 2 downto 0 do
+ 2.1 If k_i = 0 then
+ P_1 ↠[2]P_1; P_2 ↠P_1 + P_2.
+ Else
+ P_1 ↠P_1 + P_2; P_2 ↠[2]P_2.
+ 3. Return(P_1).
+
+<u>Algorithm 3.</u> in [^8] (general Montgomery ladder)
+
+ INPUT: G ∈ E(F_q), k = (1, k_{t−2}, ..., k_0)2
+ OUTPUT: Y = kG
+ R0 ↠G; R1 ↠[2]G
+ for j = t − 2 downto 0 do
+ if (k_j = 0) then
+ R1 ↠R0 + R1; R0 ↠[2]R0
+ else [if (kj = 1)]
+ R0 ↠R0 + R1; R1 ↠[2]R1
+ return R0
+
+Montgomery addition formulas (Projective coordinates/XZ coordinates):[^2]
+
+ - Addition (\( n \ne m \)):
+\begin{align*}
+X_{m+n} &= Z_{m-n}((X_m - Z_m)(X_n + Z_n) + (X_m + Z_m)(X_n - Z_n))^2 \\
+Z_{m+n} &= X_{m-n}((X_m - Z_m)(X_n + Z_n) - (X_m + Z_m)(X_n - Z_n))^2
+\end{align*}
+
+ - Doubling:
+\begin{align*}
+4X_nZ_n &= (X_n + Z_n)^2 - (X_n - Z_n)^2 \\
+X_{2n} &= (X_n + Z_n)^2 (X_n - Z_n)^2 \\
+Z_{2n} &= 4X_nZ_n((X_n - Z_n)^2 + ((A + 2)/4)(4X_nZ_n))
+\end{align*}
+
+ - \( Y \) recovery:
+\begin{align*}
+x_n &= X_n / Z_n; \qquad x_{n+1} = X_{n+1} / Z_{n+1} \\
+y_n &= \frac{(x_1x_n + 1) (x_1 + x_n + 2A) - 2A - (x_1 - x_n)^2x_{n+1}}{2By_1}
+\end{align*}
+
+### Brier-Joye (+ Lopez-Dahab) ladder
+
+Not really a scalar-multiplication algorithm. Generalization of the stricter Montgomery ladder(the *x*-coordinate only scalar-mult algo and addition formulas on Montgomery curves) to short Weierstrass elliptic curves over fields of \( \text{char}\ \mathbb{K} \ne 2, 3 \) by Brier & Joye. Furthermore the *x*-coordinate only addition formulas were generalized to curves over \( \mathbb{F}_{2^m} \) by Lopez & Dahab.
+
+Brier-Joye addition formulas (Projective coordinates/XZ coordinates):[^2]
+
+ - Addition (\( n \ne m \)):
+\begin{align*}
+X_{m+n} &= Z_{m-n}(-4a_6Z_mZ_n(X_mZ_n + X_nZ_m) + (X_mX_n - a_4 Z_mZ_n)^2) \\
+Z_{m+n} &= X_{m-n}(X_mZ_n - X_nZ_m)^2
+\end{align*}
+
+ - Doubling:
+\begin{align*}
+X_{2n} &= (X_n^2 - a_4Z_n^2)^2 - 8 a_6X_nZ_n^3 \\
+Z_{2n} &= 4Z_n(X_n(X_n^2 + a_4 Z_n^2) + a_6Z_n^3)
+\end{align*}
+
+ - \( Y \) recovery:
+\begin{align*}
+x_n &= X_n / Z_n; \qquad x_{n+1} = X_{n+1} / Z_{n+1} \\
+y_n &= \frac{2a_6 +(x_1x_n + a_4) (x_1 + x_n) - (x_1 - x_n)^2x_{n+1}}{2y_1}
+\end{align*}
+
+Lopez-Dahab addition formulas on \( E(\mathbb{F}_{2^m}) \)(Projective coordinates/XZ coordinates):[^2]
+
+ - Addition (\( n \ne m \)):
+\begin{align*}
+Z_{m+n} &= (X_mZ_n)^2 + (X_nZ_m)^2 \\
+X_{m+n} &= Z_{m+n}X_{m-n} + X_mZ_nX_nZ_m
+\end{align*}
+
+ - Doubling:
+\begin{align*}
+X_{2n} &= X_n^4 + a_6Z_n^4 = (X_n^2 + \sqrt{a_6}Z_n^2)^2 \\
+Z_{2n} &= X_n^2Z_n^2
+\end{align*}
+
+ - \( Y \) recovery:
+\begin{align*}
+x_n &= X_n / Z_n; \qquad x_{n+1} = X_{n+1} / Z_{n+1} \\
+y_n &= \frac{(x_n + x_1)((x_n + x_1)(x_{n+1} + x_1) + x_1^2 + y_1)}{x_1} + y_1
+\end{align*}
+
+### GLV scalar multiplication
+
+[^13]
+
+### Fixed-base windowing (BGMW)
+
+<u>Algorithm 3.41</u> and <u>Algorithm 3.42</u> in GECC[^1]
+
+
+### Fixed-base comb
+
+<u>Algorithm 3.44</u> and <u>Algorithm 3.45</u> in GECC[^1]
+
+### Möller-1
+
+> The method may fail in some cases in that an addition step may turn out to be a point doubling or may involve the point at infinity (which both requires special treatment and is potentially clearly visible through side channels). However, we will show that the probability of this happening is negligible if multipliers are appropriately selected: Randomly chosen e is safe.[^9]
+
+## References
+
+[^1]: HANKERSON, Darrel; MENEZES, Alfred J.; VANSTONE, Scott. Guide to Elliptic Curve Cryptography. New York, USA: Springer, 2004. ISBN 9780387218465. Available from DOI: [10.1007/b97644](https://dx.doi.org/10.1007/b97644).
+[^2]: COHEN, Henri; FREY, Gerhard; AVANZI, Roberto M.; DOCHE, Christophe; LANGE,
+Tanja; NGUYEN, Kim; VERCAUTEREN, Frederik. Handbook of Elliptic and Hyper-
+elliptic Curve Cryptography. CRC Press, 2005-07-19. Discrete Mathematics and It’s Applications, no. 34. ISBN 9781584885184.
+[^3]: BERNSTEIN, Daniel J.; LANGE, Tanja. Explicit Formulas Database, <https://www.hyperelliptic.org/EFD/>
+[^4]: <http://point-at-infinity.org/ecc/>
+[^5]: KNUTH, Donald: The Art of Computer Programming, Volume 2: Seminumerical algorithms
+[^6]: GORDON, Daniel M.: A survey of fast exponentiation methods.
+[^7]: MORAIN, Francois; OLIVOS, Jorge: Speeding up the computations on an elliptic curve using addition-subtraction chains.
+[^8]: JOYE, Marc; YEN, Sung-Ming: The Montgomery Powering Ladder.
+[^9]: MOLLER, Bodo: Securing Elliptic Curve Point Multiplication against Side-Channel Attacks.
+[^10]: MOLLER, Bodo: Improved Techniques for Fast Exponentiation.
+[^11]: MOLLER, Bodo: Fractional Windows Revisited: Improved Signed-Digit Representations for Efficient Exponentiation.
+[^12]: KOYAMA, Kenji; TSURUOKA, Yukio: Speeding up Elliptic Cryptosystems by Using a Signed Binary Window Method.
+[^13]: GALLANT, Robert P.; LAMBERT, Robert J.; VANSTONE, Scott A.: Faster point multiplication on elliptic curves with efficient endomorphisms. \ No newline at end of file
diff --git a/docs/LIBS.md b/docs/LIBS.md
index 4fac57b..d1a68d0 100644
--- a/docs/LIBS.md
+++ b/docs/LIBS.md
@@ -1,31 +1,89 @@
-# Libraries with ECC
+# Libraries with ECC support
-Libraries with at least some ECC support:
+Popular libraries with at least some ECC support:
- - [Crypto++](https://cryptopp.com/)
- [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/)
-
- [mbedTLS](https://tls.mbed.org/)
- [Nettle](http://www.lysator.liu.se/~nisse/nettle/)
- - [OpenSSL](https://www.openssl.org/)
- [OpenSSL (FIPS mode)](https://www.openssl.org/docs/fipsnotes.html)
-
- - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx)
+ - BoringSSL
- [Microsoft .NET crypto](https://docs.microsoft.com/en-us/dotnet/standard/security/cryptography-model)
-
+
# Supported libraries
- [BouncyCastle](https://bouncycastle.org/java.html)
- Java
+ - Works with the short Weierstrass curve model.
+ - Works with coordinates:
+ - Affine
+ - Projective(Homogenous)
+ - Jacobian
+ - Jacobian-Chudnovsky
+ - Jacobian-Modified
+ - Lambda-Affine?
+ - Lambda-Projective?
+ - Skewed?
+ - Multiple scalar multiplication algorithms implemented and used:
+ - Double-and-add always (DoubleAddMultiplier)
+ - Fixed point comb (FixedPointCombMultiplier)
+ - GLV (Gallant-Lambert-Vanstone) using endomorphisms (GLVMultiplier): Faster point multiplication on elliptic curves with efficient endomorphisms. <-- default, if available
+ - Binary NAF right-to-left multiplication(mixed coordinates) (MixedNafR2LMultiplier)
+ - Montgomery ladder (MontgomeryLadderMultiplier)
+ - Binary NAF right-to-left multiplication (NafR2LMultiplier)
+ - Binary NAF left-to-right multiplication (NafL2RMultiplier)
+ - Double-and-add reference implementation (ReferenceMultiplier)
+ - Window NAF left-to-right multiplication (WNafL2RMultiplier) <-- default
+ - Window Tau-NAF multiplication (WTauNafMultiplier): Improved Algorithms for Arithmetic on Anomalous Binary Curves
+ - Zeroless signed digit binary right-to-left multiplication (ZSignedDigitR2LMultiplier)
+ - Zeroless signed digit binary left-to-right multiplication (ZSignedDigitL2RMultiplier)
+ - Has custom field and point arithmetic for:
+ - Curve25519 (transformed into short Weierstrass model)
+ - SMP2 curves
+ - SECG curves
- [Sun EC](https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunEC)
- Java + C
- - [Botan](https://botan.randombit.net/), since 2.4.0 (unreleased)
+ - Uses the short Weierstrass curve model.
+ - For prime field curves:
+ - Uses 5-bit window NAF, Uses mixed Modified-Jacobian coordinates
+ for doubling and Chudnovsky Jacobian coordinates for additions (ecp_jm.c). From:
+ Brown, Hankerson, Lopez, Menezes: Software Implementation of the NIST Elliptic Curves Over Prime Fields.
+ - Contains an implementation of scalar multiplication with 4-bit sliding window, using Jacobian coordinates (ecp_jac.c)
+ - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ecp_aff.c)
+ - For binary field curves:
+ - Uses Lopez-Dahab (Montgomery) ladder, XZ coordinates (ec2_mont.c): Fast multiplication on elliptic curves over GF(2^m) without precomputation (Algorithm 2P)
+ - Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ec2_aff.c)
+ - Has some custom arithmetic for some of the NIST primes.
+ - [OpenSSL](https://www.openssl.org/)
+ - C
+ - For prime field curves:
+ - Uses Jacobian coordinates, and Montgomery ladder, also uses wNAF-based interleaving multi-exponentiation method(ec_mult.c): http://www.bmoeller.de/pdf/TI-01-08.multiexp.pdf
+ - Also uses multiplication with precomputation by wNAF splitting(ec_mult.c)
+ - For binary field curves:
+ - Uses Jacobian coordinates, and Lopez-Dahab ladder, also uses wNAF-based interleaving multi-exponentiation method(ec2_smpl.c)
+ - [Botan](https://botan.randombit.net/)
- C++
- Uses blinded(randomized) Montgomery ladder.
- - https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2
- - https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc
- - https://eprint.iacr.org/2015/657
+ - <https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2>
+ - <https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc>
+ - <https://eprint.iacr.org/2015/657>
+ - ECTester supports v2.4.0 and up.
- [libtomcrypt](http://www.libtom.net/LibTomCrypt/)
- C
- Uses Jacobian coordinates.
- - Sliding window scalar multiplication algorithm. \ No newline at end of file
+ - Sliding window scalar multiplication algorithm.
+ - [Crypto++](https://cryptopp.com/)
+ - C++
+ - For prime field curves:
+ - Uses projective coordinates and sliding window scalar multiplication algorithm.
+ - For binary field curves:
+ - Uses affine coordinates and sliding window scalar multiplication algorithm.
+ - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx)
+ - C API.
+ - Closed source.
+ - For prime field curves(only supports):
+ - Uses Short Weierstrass model.
+ - Uses Twisted Edwards model.
+ - Uses Montgomery model.
+ - Uses fixed window scalar multiplication.
+ - Uses Wnaf multi-scalar multiplication with interleaving.
+ - Uses Montgomery ladder. \ No newline at end of file
diff --git a/docs/TESTS.md b/docs/TESTS.md
index c4f38dc..5811577 100644
--- a/docs/TESTS.md
+++ b/docs/TESTS.md
@@ -1,12 +1,18 @@
-# Tests
+# Test suites
- `default`
- `test-vectors`
- - `wrong`
- - `composite`
- - `invalid`
+ - `compression`
+ - `miscellaneous`
+ - `wrong`*
+ - `composite`*
+ - `invalid`*
+ - `twist`*
+ - `degenerate`*
+ - `cofactor`*
+ - `edge-cases`*
-**NOTE: The `wrong`, `composite` and `invalid` test suites caused temporary DoS of some cards. These test suites prompt you for
+**\*NOTE: The `wrong`, `composite`, `invalid`,`twist`, `cofactor`, `edge-cases` and `degenerate` test suites caused temporary/permanent DoS of some cards. These test suites prompt you for
confirmation before running, be cautious.**
## Default
@@ -18,14 +24,10 @@ This test suite is run if no argument is provided to `-t / --test`.
For example:
```bash
-java -jar ECTester.jar -a -fp -t
+java -jar ECTester.jar -t
```
-tests all(`-a`), prime field(`-fp`), using the default test suite.
+tests prime field and binary field curves, using the default test suite.
-```bash
-java -jar ECTester.jar-a -f2m -t
-```
-tests all(`-a`), binary field(`-f2m`), curves.
## Test-Vectors
Tests using known test vectors provided by NIST/SECG/Brainpool:
@@ -40,43 +42,142 @@ Tests using known test vectors provided by NIST/SECG/Brainpool:
For example:
```bash
-java -jar ECTester.jar -t test-vectors -nc nist -a -f2m
+java -jar ECTester.jar -t test-vectors
```
-tests all(`-a`), binary field(`-f2m`) NIST curves for which test-vectors are provided. Although this test suite is better for general testing:
+tests all curves for which test-vectors are provided.
+
+## Compression
+Tests support for compression of public points in ECDH as specified in ANSI X9.62. Tests ECDH with points in compressed
+and hybrid form. Also tests card response to a hybrid point with wrong `y` coordinate and to the point at infinity(as public key in ECDH).
+
+For example:
```bash
-java -jar ECTester.jar -t test-vectors -a
+java -jar ECTester.jar -t compression
```
+
## Wrong
-Tests using the default tests on a category of wrong curves. These curves are not really curves as they have:
+Tests on a category of wrong curves. These curves are not really curves as they have:
- non-prime field in the prime-field case
- reducible polynomial as the field polynomial in the binary case
-These tests should fail generally. They are equivalent with `java -jar ECTester.jar -nc wrong -t`, the default tests over the `wrong` category
-of curves.
-
+This test suite also does some additional tests with corrupting the parameters:
+ - Fp:
+ - p = 0
+ - p = 1
+ - p = q^2; q prime
+ - p = q * s; q and s prime
+ - G = random point not on curve
+ - G = random data
+ - G = infinity
+ - r = 0
+ - r = 1
+ - r = some prime larger than original r (and \[r\]G != infinity)
+ - r = some prime smaller than original r (and \[r\]G != infninity)
+ - r = some composite number (and \[r\]G != infinity)
+ - k = 0xff
+ - k = 0
+ - F2m:
+ - e1 = e2 = e3 = 0
+ - m < e1 < e2 < e3
+
+These tests should fail generally.
+
For example:
```bash
-java -jar ECTester.jar -t wrong -b 521 -fp
+java -jar ECTester.jar -t wrong
```
-tests a 521 bit(`-b`), prime-field(`-fp`) wrong curve.
+does all wrong curve tests.
+
## Composite
Tests using curves that don't have a prime order/nearly prime order.
-These tests should generally fail, a success here implies the card **WILL** use a non-secure curve if such curve is set
+These tests should generally fail, a success here implies the card will use a non-secure curve if such curve is set
by the applet. Operations over such curves are susceptible to small-subgroup attacks.
+ - r = quite a smooth number, many small factors, r = |G|
+ - r = small prime(of increasing bit lengths), r = |G|
+ - r = p * q = |G|
+ - r = G = Carmichael number = p * q * s
+ - \[r\]G = infinity but r != |G|, so |G| divides r
+
For example:
```bash
-java -jar ECTester.jar -t composite -b 160 -fp
+java -jar ECTester.jar -t composite
```
+
## Invalid
-Tests using known named curves from several categories(SECG/NIST/Brainpool) against pregenerated *invalid* public keys.
-These tests should definitely fail, a success here implies the card is susceptible to invalid curve attacks.
+Tests using known named curves from several categories(SECG/NIST/Brainpool) against pre-generated *invalid* public keys.
+ECDH should definitely fail, a success here implies the card is susceptible to invalid curve attacks.
+See [Practical Invalid Curve Attacks on TLS-ECDH](https://www.nds.rub.de/media/nds/veroeffentlichungen/2015/09/14/main-full.pdf) for more information.
For example:
```bash
-java -jar ECTester.jar -t invalid -nc nist -a -fp
+java -jar ECTester.jar -t invalid
```
-tests using all(`-a`), prime-field(`-fp`) NIST curves and pregenerated *invalid* public keys for these curves. \ No newline at end of file
+tests using all curves with pregenerated *invalid* public keys for these curves.
+
+
+## Twist
+Tests using known named curves froms several categories(SECG/NIST) against pre-generated points on twists of said curves.
+ECDH should fail, a success here implies the card is not twist secure, if a curve with an unsecure twist is used,
+the card might compute on the twist, if a point on the twist is supplied.
+
+See [SafeCurves on twist security](https://safecurves.cr.yp.to/twist.html) for more information.
+
+For example:
+```bash
+java -jar ECTester.jar -t twist
+```
+
+## Degenerate
+Tests using known named curves froms several categories(SECG/NIST) against pre-generated points on the degenerate line
+`Y: x = 0`. ECDH should fail, a success here might mean the card does not check that the point lies on the correct curve
+and uses a curve model vulnerable to such degenerate points.
+
+See [Degenerate Curve Attacks - Extending Invalid Curve Attacks to Edwards Curves and Other Models](https://eprint.iacr.org/2015/1233.pdf) for more information.
+
+For example:
+```bash
+java -jar ECTester.jar -t degenerate
+```
+
+## Cofactor
+Tests whether the card correctly rejects points that lie on the curve but not on the subgroup generated by the specified generator
+during ECDH. Does this with curves where the cofactor subgroup has small order, then with curves that have order equal to the product
+of two large primes, sets the generator with order of one prime and tries points on the subgroup of the other prime order.
+
+For example:
+```bash
+java -jar ECTester.jar -t cofactor
+```
+
+## Edge-Cases
+Tests various inputs to ECDH which may cause an implementation to achieve a certain edge-case state during ECDH.
+Some of the data is from the google/Wycheproof project. Tests include [CVE-2017-10176](https://nvd.nist.gov/vuln/detail/CVE-2017-10176) and [CVE-2017-8932](https://nvd.nist.gov/vuln/detail/CVE-2017-8932).
+Various custom edge private key values are also tested.
+
+CVE-2017-10176 was in implementation issue in the SunEC Java library that caused the implementation to reach the point at infinity during ECDH computation.
+
+CVE-2017-8932 was an implementation issue in the Go standard library, in particular its scalar multiplication algorithm on the
+P-256 curve which leaked information about the private key.
+
+Custom private key values over SECG curves are tested:
+ - s = 0, s = 1
+ - s < r, s = r, s > r
+ - s = r - 1, s = r + 1
+ - s = k\*r - 1, s = k\*r, s = k\*r + 1
+
+For example:
+```bash
+java -jar ECTester.jar -t edge-cases
+```
+
+## Miscellaneous
+Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves and Barreto-Naehrig curves with small embedding degree and CM discriminant.
+
+For example:
+```bash
+java -jar ECTester.jar -t miscellaneous
+``` \ No newline at end of file
diff --git a/ext/ant-javacard.jar b/ext/ant-javacard.jar
index ddc4931..c4fb69e 100644
--- a/ext/ant-javacard.jar
+++ b/ext/ant-javacard.jar
Binary files differ
diff --git a/ext/globalplatform-2_1_1/gp211.jar b/ext/globalplatform-2_1_1/gp211.jar
deleted file mode 100644
index baf03d9..0000000
--- a/ext/globalplatform-2_1_1/gp211.jar
+++ /dev/null
Binary files differ
diff --git a/ext/globalplatform-2_1_1/org/globalplatform/javacard/globalplatform.exp b/ext/globalplatform-2_1_1/org/globalplatform/javacard/globalplatform.exp
deleted file mode 100644
index 9c50aae..0000000
--- a/ext/globalplatform-2_1_1/org/globalplatform/javacard/globalplatform.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/api_export_files/java/io/javacard/io.exp b/ext/java_card_kit-2_2_1/api_export_files/java/io/javacard/io.exp
deleted file mode 100644
index 931133a..0000000
--- a/ext/java_card_kit-2_2_1/api_export_files/java/io/javacard/io.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/api_export_files/java/lang/javacard/lang.exp b/ext/java_card_kit-2_2_1/api_export_files/java/lang/javacard/lang.exp
deleted file mode 100644
index f349818..0000000
--- a/ext/java_card_kit-2_2_1/api_export_files/java/lang/javacard/lang.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/api_export_files/java/rmi/javacard/rmi.exp b/ext/java_card_kit-2_2_1/api_export_files/java/rmi/javacard/rmi.exp
deleted file mode 100644
index 209cdf3..0000000
--- a/ext/java_card_kit-2_2_1/api_export_files/java/rmi/javacard/rmi.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/api_export_files/javacard/framework/javacard/framework.exp b/ext/java_card_kit-2_2_1/api_export_files/javacard/framework/javacard/framework.exp
deleted file mode 100644
index 7deb667..0000000
--- a/ext/java_card_kit-2_2_1/api_export_files/javacard/framework/javacard/framework.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/api_export_files/javacard/framework/service/javacard/service.exp b/ext/java_card_kit-2_2_1/api_export_files/javacard/framework/service/javacard/service.exp
deleted file mode 100644
index 8fbef2f..0000000
--- a/ext/java_card_kit-2_2_1/api_export_files/javacard/framework/service/javacard/service.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/api_export_files/javacard/security/javacard/security.exp b/ext/java_card_kit-2_2_1/api_export_files/javacard/security/javacard/security.exp
deleted file mode 100644
index ece3b83..0000000
--- a/ext/java_card_kit-2_2_1/api_export_files/javacard/security/javacard/security.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/api_export_files/javacardx/crypto/javacard/crypto.exp b/ext/java_card_kit-2_2_1/api_export_files/javacardx/crypto/javacard/crypto.exp
deleted file mode 100644
index 3df48b1..0000000
--- a/ext/java_card_kit-2_2_1/api_export_files/javacardx/crypto/javacard/crypto.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/bin/apdutool b/ext/java_card_kit-2_2_1/bin/apdutool
deleted file mode 100644
index 5a1391b..0000000
--- a/ext/java_card_kit-2_2_1/bin/apdutool
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.apdutool.Main "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/capdump b/ext/java_card_kit-2_2_1/bin/capdump
deleted file mode 100644
index dadebd1..0000000
--- a/ext/java_card_kit-2_2_1/bin/capdump
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.capdump.CapDump "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/capgen b/ext/java_card_kit-2_2_1/bin/capgen
deleted file mode 100644
index d0abad1..0000000
--- a/ext/java_card_kit-2_2_1/bin/capgen
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.jcasm.cap.Main "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/converter b/ext/java_card_kit-2_2_1/bin/converter
deleted file mode 100644
index 70e9db7..0000000
--- a/ext/java_card_kit-2_2_1/bin/converter
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.converter.Converter "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/cref b/ext/java_card_kit-2_2_1/bin/cref
deleted file mode 100644
index 3244115..0000000
--- a/ext/java_card_kit-2_2_1/bin/cref
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/bin/exp2text b/ext/java_card_kit-2_2_1/bin/exp2text
deleted file mode 100644
index d88da73..0000000
--- a/ext/java_card_kit-2_2_1/bin/exp2text
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.converter.Exp2Text "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/jcwde b/ext/java_card_kit-2_2_1/bin/jcwde
deleted file mode 100644
index c51669b..0000000
--- a/ext/java_card_kit-2_2_1/bin/jcwde
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.jcwde.Main "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/scriptgen b/ext/java_card_kit-2_2_1/bin/scriptgen
deleted file mode 100644
index 2df519b..0000000
--- a/ext/java_card_kit-2_2_1/bin/scriptgen
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.scriptgen.Main "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/verifycap b/ext/java_card_kit-2_2_1/bin/verifycap
deleted file mode 100644
index 28256d9..0000000
--- a/ext/java_card_kit-2_2_1/bin/verifycap
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.offcardverifier.Verifier "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/verifyexp b/ext/java_card_kit-2_2_1/bin/verifyexp
deleted file mode 100644
index dc4c4fd..0000000
--- a/ext/java_card_kit-2_2_1/bin/verifyexp
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.offcardverifier.VerifyExp "$@"
diff --git a/ext/java_card_kit-2_2_1/bin/verifyrev b/ext/java_card_kit-2_2_1/bin/verifyrev
deleted file mode 100644
index 55b8158..0000000
--- a/ext/java_card_kit-2_2_1/bin/verifyrev
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.offcardverifier.VerifyRev "$@"
diff --git a/ext/java_card_kit-2_2_1/lib/apduio.jar b/ext/java_card_kit-2_2_1/lib/apduio.jar
deleted file mode 100644
index b74da00..0000000
--- a/ext/java_card_kit-2_2_1/lib/apduio.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/apdutool.jar b/ext/java_card_kit-2_2_1/lib/apdutool.jar
deleted file mode 100644
index dae00af..0000000
--- a/ext/java_card_kit-2_2_1/lib/apdutool.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/api.jar b/ext/java_card_kit-2_2_1/lib/api.jar
deleted file mode 100644
index e8ea0ad..0000000
--- a/ext/java_card_kit-2_2_1/lib/api.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/capdump.jar b/ext/java_card_kit-2_2_1/lib/capdump.jar
deleted file mode 100644
index a30ecd7..0000000
--- a/ext/java_card_kit-2_2_1/lib/capdump.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/converter.jar b/ext/java_card_kit-2_2_1/lib/converter.jar
deleted file mode 100644
index a9ad89d..0000000
--- a/ext/java_card_kit-2_2_1/lib/converter.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/installer.jar b/ext/java_card_kit-2_2_1/lib/installer.jar
deleted file mode 100644
index 55928d3..0000000
--- a/ext/java_card_kit-2_2_1/lib/installer.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/javacardframework.jar b/ext/java_card_kit-2_2_1/lib/javacardframework.jar
deleted file mode 100644
index d16b86d..0000000
--- a/ext/java_card_kit-2_2_1/lib/javacardframework.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/jcclientsamples.jar b/ext/java_card_kit-2_2_1/lib/jcclientsamples.jar
deleted file mode 100644
index bba7f43..0000000
--- a/ext/java_card_kit-2_2_1/lib/jcclientsamples.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/jcrmiclientframework.jar b/ext/java_card_kit-2_2_1/lib/jcrmiclientframework.jar
deleted file mode 100644
index 3d04f6f..0000000
--- a/ext/java_card_kit-2_2_1/lib/jcrmiclientframework.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/jcwde.jar b/ext/java_card_kit-2_2_1/lib/jcwde.jar
deleted file mode 100644
index c748f26..0000000
--- a/ext/java_card_kit-2_2_1/lib/jcwde.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/offcardverifier.jar b/ext/java_card_kit-2_2_1/lib/offcardverifier.jar
deleted file mode 100644
index 2369c14..0000000
--- a/ext/java_card_kit-2_2_1/lib/offcardverifier.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_1/lib/scriptgen.jar b/ext/java_card_kit-2_2_1/lib/scriptgen.jar
deleted file mode 100644
index 64f9d96..0000000
--- a/ext/java_card_kit-2_2_1/lib/scriptgen.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/java/io/javacard/io.exp b/ext/java_card_kit-2_2_2/api_export_files/java/io/javacard/io.exp
deleted file mode 100644
index 931133a..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/java/io/javacard/io.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/java/lang/javacard/lang.exp b/ext/java_card_kit-2_2_2/api_export_files/java/lang/javacard/lang.exp
deleted file mode 100644
index f349818..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/java/lang/javacard/lang.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/java/rmi/javacard/rmi.exp b/ext/java_card_kit-2_2_2/api_export_files/java/rmi/javacard/rmi.exp
deleted file mode 100644
index 209cdf3..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/java/rmi/javacard/rmi.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacard/framework/javacard/framework.exp b/ext/java_card_kit-2_2_2/api_export_files/javacard/framework/javacard/framework.exp
deleted file mode 100644
index 9e9351b..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacard/framework/javacard/framework.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacard/framework/service/javacard/service.exp b/ext/java_card_kit-2_2_2/api_export_files/javacard/framework/service/javacard/service.exp
deleted file mode 100644
index 8fbef2f..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacard/framework/service/javacard/service.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacard/security/javacard/security.exp b/ext/java_card_kit-2_2_2/api_export_files/javacard/security/javacard/security.exp
deleted file mode 100644
index d3279d4..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacard/security/javacard/security.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacardx/apdu/javacard/apdu.exp b/ext/java_card_kit-2_2_2/api_export_files/javacardx/apdu/javacard/apdu.exp
deleted file mode 100644
index c9183d4..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacardx/apdu/javacard/apdu.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacardx/biometry/javacard/biometry.exp b/ext/java_card_kit-2_2_2/api_export_files/javacardx/biometry/javacard/biometry.exp
deleted file mode 100644
index fb46fa3..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacardx/biometry/javacard/biometry.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacardx/crypto/javacard/crypto.exp b/ext/java_card_kit-2_2_2/api_export_files/javacardx/crypto/javacard/crypto.exp
deleted file mode 100644
index a9968bb..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacardx/crypto/javacard/crypto.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacardx/external/javacard/external.exp b/ext/java_card_kit-2_2_2/api_export_files/javacardx/external/javacard/external.exp
deleted file mode 100644
index 4af91e5..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacardx/external/javacard/external.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/math/javacard/math.exp b/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/math/javacard/math.exp
deleted file mode 100644
index 89a1ac6..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/math/javacard/math.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/tlv/javacard/tlv.exp b/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/tlv/javacard/tlv.exp
deleted file mode 100644
index 58495fb..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/tlv/javacard/tlv.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/util/intx/javacard/intx.exp b/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/util/intx/javacard/intx.exp
deleted file mode 100644
index 881a961..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/util/intx/javacard/intx.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/util/javacard/util.exp b/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/util/javacard/util.exp
deleted file mode 100644
index 3ce0d16..0000000
--- a/ext/java_card_kit-2_2_2/api_export_files/javacardx/framework/util/javacard/util.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/bin/apdutool b/ext/java_card_kit-2_2_2/bin/apdutool
deleted file mode 100644
index 128e724..0000000
--- a/ext/java_card_kit-2_2_2/bin/apdutool
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.apdutool.Main "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/capdump b/ext/java_card_kit-2_2_2/bin/capdump
deleted file mode 100644
index 3877c3a..0000000
--- a/ext/java_card_kit-2_2_2/bin/capdump
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.capdump.CapDump "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/capgen b/ext/java_card_kit-2_2_2/bin/capgen
deleted file mode 100644
index f054c6b..0000000
--- a/ext/java_card_kit-2_2_2/bin/capgen
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.jcasm.cap.Main "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/converter b/ext/java_card_kit-2_2_2/bin/converter
deleted file mode 100644
index e99bb8e..0000000
--- a/ext/java_card_kit-2_2_2/bin/converter
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.converter.Converter "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/cref b/ext/java_card_kit-2_2_2/bin/cref
deleted file mode 100644
index b0d8ac8..0000000
--- a/ext/java_card_kit-2_2_2/bin/cref
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/bin/exp2text b/ext/java_card_kit-2_2_2/bin/exp2text
deleted file mode 100644
index 6350fac..0000000
--- a/ext/java_card_kit-2_2_2/bin/exp2text
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.converter.Exp2Text "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/jcwde b/ext/java_card_kit-2_2_2/bin/jcwde
deleted file mode 100644
index f59a861..0000000
--- a/ext/java_card_kit-2_2_2/bin/jcwde
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.jcwde.Main "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/libjpcsclite.so b/ext/java_card_kit-2_2_2/bin/libjpcsclite.so
deleted file mode 100644
index 4ffb8b1..0000000
--- a/ext/java_card_kit-2_2_2/bin/libjpcsclite.so
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/bin/scriptgen b/ext/java_card_kit-2_2_2/bin/scriptgen
deleted file mode 100644
index 3a1e310..0000000
--- a/ext/java_card_kit-2_2_2/bin/scriptgen
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.scriptgen.Main "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/verifycap b/ext/java_card_kit-2_2_2/bin/verifycap
deleted file mode 100644
index 6d4ae0b..0000000
--- a/ext/java_card_kit-2_2_2/bin/verifycap
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.offcardverifier.Verifier "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/verifyexp b/ext/java_card_kit-2_2_2/bin/verifyexp
deleted file mode 100644
index 9120515..0000000
--- a/ext/java_card_kit-2_2_2/bin/verifyexp
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.offcardverifier.VerifyExp "$@"
diff --git a/ext/java_card_kit-2_2_2/bin/verifyrev b/ext/java_card_kit-2_2_2/bin/verifyrev
deleted file mode 100644
index c231efb..0000000
--- a/ext/java_card_kit-2_2_2/bin/verifyrev
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-JAVA_HOME=${JAVA_HOME:-/usr/j2se}
-
-bin_home=`dirname $0`
-JC_HOME=${JC_HOME:-$bin_home/..}
-
-JC_PATH=$JC_HOME/lib/apdutool.jar:$JC_HOME/lib/apduio.jar:$JC_HOME/lib/converter.jar:$JC_HOME/lib/jcwde.jar:$JC_HOME/lib/scriptgen.jar:$JC_HOME/lib/offcardverifier.jar:$JC_HOME/lib/api.jar:$JC_HOME/lib/installer.jar:$JC_HOME/lib/capdump.jar:$JC_HOME/samples/classes:$CLASSPATH
-
-JFLAGS="-classpath $JC_PATH"
-$JAVA_HOME/bin/java $JFLAGS com.sun.javacard.offcardverifier.VerifyRev "$@"
diff --git a/ext/java_card_kit-2_2_2/lib/apduio.jar b/ext/java_card_kit-2_2_2/lib/apduio.jar
deleted file mode 100644
index ab57e26..0000000
--- a/ext/java_card_kit-2_2_2/lib/apduio.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/apdutool.jar b/ext/java_card_kit-2_2_2/lib/apdutool.jar
deleted file mode 100644
index c4ad9f2..0000000
--- a/ext/java_card_kit-2_2_2/lib/apdutool.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/api.jar b/ext/java_card_kit-2_2_2/lib/api.jar
deleted file mode 100644
index 98e07b2..0000000
--- a/ext/java_card_kit-2_2_2/lib/api.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/api_16.jar b/ext/java_card_kit-2_2_2/lib/api_16.jar
deleted file mode 100644
index 6213631..0000000
--- a/ext/java_card_kit-2_2_2/lib/api_16.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/capdump.jar b/ext/java_card_kit-2_2_2/lib/capdump.jar
deleted file mode 100644
index 00f38c5..0000000
--- a/ext/java_card_kit-2_2_2/lib/capdump.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/converter.jar b/ext/java_card_kit-2_2_2/lib/converter.jar
deleted file mode 100644
index 3728ebe..0000000
--- a/ext/java_card_kit-2_2_2/lib/converter.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/installer.jar b/ext/java_card_kit-2_2_2/lib/installer.jar
deleted file mode 100644
index 43004d5..0000000
--- a/ext/java_card_kit-2_2_2/lib/installer.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/javacardframework.jar b/ext/java_card_kit-2_2_2/lib/javacardframework.jar
deleted file mode 100644
index 35762c4..0000000
--- a/ext/java_card_kit-2_2_2/lib/javacardframework.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/jcclientsamples.jar b/ext/java_card_kit-2_2_2/lib/jcclientsamples.jar
deleted file mode 100644
index c169891..0000000
--- a/ext/java_card_kit-2_2_2/lib/jcclientsamples.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/jcrmiclientframework.jar b/ext/java_card_kit-2_2_2/lib/jcrmiclientframework.jar
deleted file mode 100644
index c0fdaad..0000000
--- a/ext/java_card_kit-2_2_2/lib/jcrmiclientframework.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/jcwde.jar b/ext/java_card_kit-2_2_2/lib/jcwde.jar
deleted file mode 100644
index 1f6d017..0000000
--- a/ext/java_card_kit-2_2_2/lib/jcwde.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/jcwde_16.jar b/ext/java_card_kit-2_2_2/lib/jcwde_16.jar
deleted file mode 100644
index 76de86b..0000000
--- a/ext/java_card_kit-2_2_2/lib/jcwde_16.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/offcardverifier.jar b/ext/java_card_kit-2_2_2/lib/offcardverifier.jar
deleted file mode 100644
index e6b00a9..0000000
--- a/ext/java_card_kit-2_2_2/lib/offcardverifier.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-2_2_2/lib/scriptgen.jar b/ext/java_card_kit-2_2_2/lib/scriptgen.jar
deleted file mode 100644
index e1b50c5..0000000
--- a/ext/java_card_kit-2_2_2/lib/scriptgen.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/COPYRIGHT.html b/ext/java_card_kit-3_0_3/COPYRIGHT.html
deleted file mode 100644
index 66af699..0000000
--- a/ext/java_card_kit-3_0_3/COPYRIGHT.html
+++ /dev/null
@@ -1,171 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
-<html>
-<head>
- <meta http-equiv="Content-Type"
- content="text/html; charset=ISO-8859-1">
- <meta http-equiv="Content-Style-Type" content="text/css">
- <meta name="GENERATOR"
- content="Adobe FrameMaker 7.0/HTML Export Filter">
- <link rel="STYLESHEET" href="document.css" charset="ISO-8859-1"
- type="text/css">
- <title>Copyright</title>
-</head>
-<body style="background-color: rgb(255, 255, 255);">
-<div><span style="font-weight: bold;">Copyright &copy; 1998, 2010,
-Oracle and/or its affiliates. All rights reserved.</span><span
- style="font-weight: bold;"><br>
-</span>
-<p>This software and related documentation are provided under a license
-agreement containing restrictions on use and disclosure and are
-protected by intellectual property laws. Except as expressly permitted
-in your license agreement or allowed by law, you may not use, copy,
-reproduce, translate, broadcast, modify, license, transmit, distribute,
-exhibit, perform, publish, or display any part, in any form, or by any
-means. Reverse engineering, disassembly, or decompilation of this
-software, unless required by law for interoperability, is prohibited.</p>
-<p>The information contained herein is subject to change without notice
-and is not warranted to be error-free. If you find any errors, please
-report them to us in writing.</p>
-<p>If this is software or related software documentation that is
-delivered to the U.S. Government or anyone licensing it on behalf of
-the U.S. Government, the following notice is applicable:</p>
-<p>U.S. GOVERNMENT RIGHTS Programs, software, databases, and related
-documentation and technical data delivered to U.S. Government customers
-are "commercial computer software" or "commercial technical data"
-pursuant to the applicable Federal Acquisition Regulation and
-agency-specific supplemental regulations. As such, the use,
-duplication, disclosure, modification, and adaptation shall be subject
-to the restrictions and license terms set forth in the applicable
-Government contract, and, to the extent applicable by the terms of the
-Government contract, the additional rights set forth in FAR 52.227-19,
-Commercial Computer Software License (December 2007). Oracle USA, Inc.,
-500 Oracle Parkway, Redwood City, CA 94065.</p>
-<p>This software or hardware is developed for general use in a variety
-of information management applications. It is not developed or intended
-for use in any inherently dangerous applications, including
-applications which may create a risk of personal injury. If you use
-this software or hardware in dangerous applications, then you shall be
-responsible to take all appropriate fail-safe, backup, redundancy, and
-other measures to ensure the safe use. Oracle Corporation and its
-affiliates disclaim any liability for any damages caused by use of this
-software or hardware in dangerous applications.</p>
-<p>Oracle and Java are registered trademarks of Oracle Corporation
-and/or its
-affiliates. Oracle and Java are registered trademarks of Oracle and/or
-its affiliates. Other names may be trademarks of their respective
-owners.</p>
-<p>AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks
-or registered trademarks of Advanced Micro Devices. Intel and Intel
-Xeon are trademarks or registered trademarks of Intel Corporation. All
-SPARC trademarks are used under license and are trademarks or
-registered trademarks of SPARC International, Inc. UNIX is a registered
-trademark licensed through X/Open Company, Ltd.</p>
-<p>This software or hardware and documentation may provide access to or
-information on content, products, and services from third parties.
-Oracle Corporation and its affiliates are not responsible for and
-expressly disclaim all warranties of any kind with respect to
-third-party content, products, and services. Oracle Corporation and its
-affiliates will not be responsible for any loss, costs, or damages
-incurred due to your access to or use of third-party content, products,
-or services.<br>
-</p>
-<br>
-<span style="font-weight: bold;">Copyright &copy; 1998, 2010, Oracle
-et/ou ses affili&eacute;s.
-Tous droits r&eacute;serv&eacute;s.
-</span>
-<p>Ce logiciel et la documentation qui l&#8217;accompagne sont
-prot&eacute;g&eacute;s par les
-lois sur la propri&eacute;t&eacute; intellectuelle. Ils sont
-conc&eacute;d&eacute;s sous licence et soumis &agrave;
-des restrictions d&#8217;utilisation et de divulgation. Sauf disposition de
-votre contrat de licence ou
-de la loi, vous ne pouvez pas copier, reproduire, traduire, diffuser,
-modifier, breveter,
-transmettre, distribuer, exposer, ex&eacute;cuter, publier ou afficher
-le logiciel, m&ecirc;me partiellement, sous quelque forme
-et par quelque proc&eacute;d&eacute; que ce soit. Par ailleurs, il est
-interdit de
-proc&eacute;der &agrave; toute ing&eacute;nierie inverse du logiciel,
-de le d&eacute;sassembler ou de le d&eacute;compiler,
-except&eacute; &agrave; des fins d&#8217;interop&eacute;rabilit&eacute; avec
-des logiciels tiers ou tel que prescrit par
-la loi.</p>
-<p>Les informations fournies dans ce document sont susceptibles de
-modification sans pr&eacute;avis.
-Par ailleurs, Oracle Corporation ne garantit pas qu&#8217;elles soient
-exemptes d&#8217;erreurs et vous invite,
-le cas &eacute;ch&eacute;ant, &agrave; lui en faire part par
-&eacute;crit.</p>
-<p>Si ce logiciel, ou
-la documentation qui l&#8217;accompagne, est conc&eacute;d&eacute; sous
-licence au Gouvernement des Etats-Unis, ou &agrave;
-toute entit&eacute; qui d&eacute;livre la licence de ce logiciel ou
-l&#8217;utilise pour le
-compte du Gouvernement des Etats-Unis, la notice suivante s&#8217;applique:</p>
-<p>U.S. GOVERNMENT RIGHTS. Programs,
-software, databases, and related documentation and technical data
-delivered to U.S. Government customers are
-"commercial computer software" or "commercial technical data" pursuant
-to the applicable Federal Acquisition
-Regulation and agency-specific supplemental regulations. As such, the
-use, duplication, disclosure, modification, and
-adaptation shall be subject to the restrictions and license terms set
-forth in
-the applicable Government contract, and, to the extent applicable by
-the terms of the
-Government contract, the additional rights set forth in FAR 52.227-19,
-Commercial Computer Software
-License (December 2007). Oracle America, Inc., 500 Oracle Parkway,
-Redwood City, CA
-94065.</p>
-<p>Ce logiciel ou mat&eacute;riel a &eacute;t&eacute;
-d&eacute;velopp&eacute; pour un usage g&eacute;n&eacute;ral dans le
-cadre d&#8217;applications de gestion des informations. Ce logiciel ou
-mat&eacute;riel n&#8217;est pas con&ccedil;u ni
-n&#8217;est destin&eacute; &agrave; &ecirc;tre utilis&eacute; dans des
-applications &agrave; risque, notamment dans des applications
-pouvant causer des dommages corporels. Si vous utilisez ce logiciel ou
-mat&eacute;riel dans
-le cadre d&#8217;applications dangereuses, il est de votre
-responsabilit&eacute; de prendre toutes les mesures
-de secours, de sauvegarde, de redondance et autres mesures
-n&eacute;cessaires &agrave; son utilisation
-dans des conditions optimales de s&eacute;curit&eacute;. Oracle
-Corporation et ses affili&eacute;s d&eacute;clinent toute
-responsabilit&eacute;
-quant aux dommages caus&eacute;s par l&#8217;utilisation de ce logiciel ou
-mat&eacute;riel pour ce type
-d&#8217;applications.</p>
-<p>Oracle et Java sont des marques d&eacute;pos&eacute;es d&#8217;Oracle
-Corporation et/ou de ses affili&eacute;s.Tout
-autre nom mentionn&eacute; peut correspondre &agrave; des marques
-appartenant &agrave; d&#8217;autres propri&eacute;taires qu&#8217;Oracle.</p>
-<p>AMD, Opteron,
-le logo AMD et le logo AMD Opteron sont des marques ou des
-marques d&eacute;pos&eacute;es d&#8217;Advanced Micro Devices. Intel et Intel
-Xeon sont des marques ou
-des marques d&eacute;pos&eacute;es d&#8217;Intel Corporation. Toutes les
-marques SPARC sont utilis&eacute;es sous licence et
-sont des marques ou des marques d&eacute;pos&eacute;es de SPARC
-International, Inc. UNIX est une
-marque d&eacute;pos&eacute;e conc&eacute;d&eacute;e sous licence par
-X/Open Company, Ltd.</p>
-<p>Ce logiciel ou mat&eacute;riel et
-la documentation qui l&#8217;accompagne peuvent fournir des informations ou
-des liens donnant acc&egrave;s &agrave;
-des contenus, des produits et des services &eacute;manant de tiers.
-Oracle Corporation et
-ses affili&eacute;s d&eacute;clinent toute responsabilit&eacute; ou
-garantie expresse quant aux contenus, produits ou services
-&eacute;manant de tiers. En aucun cas, Oracle Corporation et ses
-affili&eacute;s ne sauraient
-&ecirc;tre tenus pour responsables des pertes subies, des co&ucirc;ts
-occasionn&eacute;s ou des dommages caus&eacute;s
-par l&#8217;acc&egrave;s &agrave; des contenus, produits ou services tiers,
-ou &agrave; leur utilisation.<br>
-</p>
-<p class="Paragraph-Credits"></p>
-</div>
-</body>
-</html>
diff --git a/ext/java_card_kit-3_0_3/api_export_files/java/io/javacard/io.exp b/ext/java_card_kit-3_0_3/api_export_files/java/io/javacard/io.exp
deleted file mode 100644
index 931133a..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/java/io/javacard/io.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/java/lang/javacard/lang.exp b/ext/java_card_kit-3_0_3/api_export_files/java/lang/javacard/lang.exp
deleted file mode 100644
index f349818..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/java/lang/javacard/lang.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/java/rmi/javacard/rmi.exp b/ext/java_card_kit-3_0_3/api_export_files/java/rmi/javacard/rmi.exp
deleted file mode 100644
index 209cdf3..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/java/rmi/javacard/rmi.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacard/framework/javacard/framework.exp b/ext/java_card_kit-3_0_3/api_export_files/javacard/framework/javacard/framework.exp
deleted file mode 100644
index 50b66e0..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacard/framework/javacard/framework.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacard/framework/service/javacard/service.exp b/ext/java_card_kit-3_0_3/api_export_files/javacard/framework/service/javacard/service.exp
deleted file mode 100644
index 8fbef2f..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacard/framework/service/javacard/service.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacard/security/javacard/security.exp b/ext/java_card_kit-3_0_3/api_export_files/javacard/security/javacard/security.exp
deleted file mode 100644
index 994455e..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacard/security/javacard/security.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacardx/apdu/javacard/apdu.exp b/ext/java_card_kit-3_0_3/api_export_files/javacardx/apdu/javacard/apdu.exp
deleted file mode 100644
index c9183d4..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacardx/apdu/javacard/apdu.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacardx/biometry/javacard/biometry.exp b/ext/java_card_kit-3_0_3/api_export_files/javacardx/biometry/javacard/biometry.exp
deleted file mode 100644
index fb46fa3..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacardx/biometry/javacard/biometry.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacardx/crypto/javacard/crypto.exp b/ext/java_card_kit-3_0_3/api_export_files/javacardx/crypto/javacard/crypto.exp
deleted file mode 100644
index 7146e93..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacardx/crypto/javacard/crypto.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacardx/external/javacard/external.exp b/ext/java_card_kit-3_0_3/api_export_files/javacardx/external/javacard/external.exp
deleted file mode 100644
index 4af91e5..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacardx/external/javacard/external.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/math/javacard/math.exp b/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/math/javacard/math.exp
deleted file mode 100644
index 89a1ac6..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/math/javacard/math.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/tlv/javacard/tlv.exp b/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/tlv/javacard/tlv.exp
deleted file mode 100644
index 58495fb..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/tlv/javacard/tlv.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/util/intx/javacard/intx.exp b/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/util/intx/javacard/intx.exp
deleted file mode 100644
index 881a961..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/util/intx/javacard/intx.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/util/javacard/util.exp b/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/util/javacard/util.exp
deleted file mode 100644
index 3ce0d16..0000000
--- a/ext/java_card_kit-3_0_3/api_export_files/javacardx/framework/util/javacard/util.exp
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/legal/Distribution_ReadME.txt b/ext/java_card_kit-3_0_3/legal/Distribution_ReadME.txt
deleted file mode 100644
index 37560c9..0000000
--- a/ext/java_card_kit-3_0_3/legal/Distribution_ReadME.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-DistributionREADME
-
-DISTRIBUTION BY DEVELOPERS. Subject to the terms and conditions of the Software License Agreement and the obligations, restrictions, and exceptions set forth below, You may reproduce and distribute the portions of Software identified below ("Redistributable"), provided that:
-
-(a) You distribute Redistributable complete and unmodified and only bundled as part of Your Programs,
-
-(b) Your Programs add significant and primary functionality to the Redistributable,
-
-(c) You do not distribute additional software intended to replace any
-component(s) of the Redistributable,
-
-(d) You do not remove or alter any proprietary legends or notices contained in or on the Redistributable.
-
-(e) You only distribute the Redistributable subject to a license agreement that protects Oracle's interests consistent with the terms contained in this
-Agreement, and
-
-(f) You agree to defend and indemnify Oracle and its licensors from and against any damages, costs, liabilities, settlement amounts and/or expenses (including attorneys' fees) incurred in connection with any claim, lawsuit or action by any third party that arises or results from the use or distribution of any and all Programs and/or Redistributable.
-
-The following files are Redistributables:
-
-Java Card Development Kit 3.0.3
diff --git a/ext/java_card_kit-3_0_3/legal/THIRDPARTYREADME.txt b/ext/java_card_kit-3_0_3/legal/THIRDPARTYREADME.txt
deleted file mode 100644
index 1c5c2c0..0000000
--- a/ext/java_card_kit-3_0_3/legal/THIRDPARTYREADME.txt
+++ /dev/null
@@ -1,1246 +0,0 @@
-DO NOT TRANSLATE OR LOCALIZE
-
-***************************************************************************
-
-%%The following software may be included in this product:
-ASM
-
-Use of any of this software is governed by the terms of the license below:
-
-Copyright (c) 2000-2005 INRIA, France Telecom
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holders nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-THE POSSIBILITY OF SUCH DAMAGE.
-
-***************************************************************************
-
-%%The following software may be included in this product:
-Izpack
-
-Use of any of this software is governed by the terms of the license below:
-
-Apache License
-Version 2.0, January 2004
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and
-distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright
-owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities
-that control, are controlled by, or are under common control with that entity.
-For the purposes of this definition, "control" means (i) the power, direct or
-indirect, to cause the direction or management of such entity, whether by
-contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
-outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising
-permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including
-but not limited to software source code, documentation source, and configuration
-files.
-
-"Object" form shall mean any form resulting from mechanical transformation or
-translation of a Source form, including but not limited to compiled object code,
-generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made
-available under the License, as indicated by a copyright notice that is included
-in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that
-is based on (or derived from) the Work and for which the editorial revisions,
-annotations, elaborations, or other modifications represent, as a whole, an
-original work of authorship. For the purposes of this License, Derivative Works
-shall not include works that remain separable from, or merely link (or bind by
-name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version
-of the Work and any modifications or additions to that Work or Derivative Works
-thereof, that is intentionally submitted to Licensor for inclusion in the Work
-by the copyright owner or by an individual or Legal Entity authorized to submit
-on behalf of the copyright owner. For the purposes of this definition,
-"submitted" means any form of electronic, verbal, or written communication sent
-to the Licensor or its representatives, including but not limited to
-communication on electronic mailing lists, source code control systems, and
-issue tracking systems that are managed by, or on behalf of, the Licensor for
-the purpose of discussing and improving the Work, but excluding communication
-that is conspicuously marked or otherwise designated in writing by the copyright
-owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
-of whom a Contribution has been received by Licensor and subsequently
-incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of this
-License, each Contributor hereby grants to You a perpetual, worldwide,
-non-exclusive, no-charge, royalty-free, irrevocable copyright license to
-reproduce, prepare Derivative Works of, publicly display, publicly perform,
-sublicense, and distribute the Work and such Derivative Works in Source or
-Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of this License,
-each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
-no-charge, royalty-free, irrevocable (except as stated in this section) patent
-license to make, have made, use, offer to sell, sell, import, and otherwise
-transfer the Work, where such license applies only to those patent claims
-licensable by such Contributor that are necessarily infringed by their
-Contribution(s) alone or by combination of their Contribution(s) with the Work
-to which such Contribution(s) was submitted. If You institute patent litigation
-against any entity (including a cross-claim or counterclaim in a lawsuit)
-alleging that the Work or a Contribution incorporated within the Work
-constitutes direct or contributory patent infringement, then any patent licenses
-granted to You under this License for that Work shall terminate as of the date
-such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the Work or
-Derivative Works thereof in any medium, with or without modifications, and in
-Source or Object form, provided that You meet the following conditions:
-
- 1. You must give any other recipients of the Work or Derivative Works a copy
-of this License; and
-
- 2. You must cause any modified files to carry prominent notices stating that
-You changed the files; and
-
- 3. You must retain, in the Source form of any Derivative Works that You
-distribute, all copyright, patent, trademark, and attribution notices from the
-Source form of the Work, excluding those notices that do not pertain to any part
-of the Derivative Works; and
-
- 4. If the Work includes a "NOTICE" text file as part of its distribution,
-then any Derivative Works that You distribute must include a readable copy of
-the attribution notices contained within such NOTICE file, excluding those
-notices that do not pertain to any part of the Derivative Works, in at least one
-of the following places: within a NOTICE text file distributed as part of the
-Derivative Works; within the Source form or documentation, if provided along
-with the Derivative Works; or, within a display generated by the Derivative
-Works, if and wherever such third-party notices normally appear. The contents of
-the NOTICE file are for informational purposes only and do not modify the
-License. You may add Your own attribution notices within Derivative Works that
-You distribute, alongside or as an addendum to the NOTICE text from the Work,
-provided that such additional attribution notices cannot be construed as
-modifying the License.
-
-You may add Your own copyright statement to Your modifications and may provide
-additional or different license terms and conditions for use, reproduction, or
-distribution of Your modifications, or for any such Derivative Works as a whole,
-provided Your use, reproduction, and distribution of the Work otherwise complies
-with the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise, any
-Contribution intentionally submitted for inclusion in the Work by You to the
-Licensor shall be under the terms and conditions of this License, without any
-additional terms or conditions. Notwithstanding the above, nothing herein shall
-supersede or modify the terms of any separate license agreement you may have
-executed with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade names,
-trademarks, service marks, or product names of the Licensor, except as required
-for reasonable and customary use in describing the origin of the Work and
-reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
-writing, Licensor provides the Work (and each Contributor provides its
-Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied, including, without limitation, any warranties
-or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-PARTICULAR PURPOSE. You are solely responsible for determining the
-appropriateness of using or redistributing the Work and assume any risks
-associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory, whether in
-tort (including negligence), contract, or otherwise, unless required by
-applicable law (such as deliberate and grossly negligent acts) or agreed to in
-writing, shall any Contributor be liable to You for damages, including any
-direct, indirect, special, incidental, or consequential damages of any character
-arising as a result of this License or out of the use or inability to use the
-Work (including but not limited to damages for loss of goodwill, work stoppage,
-computer failure or malfunction, or any and all other commercial damages or
-losses), even if such Contributor has been advised of the possibility of such
-damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing the Work or
-Derivative Works thereof, You may choose to offer, and charge a fee for,
-acceptance of support, warranty, indemnity, or other liability obligations
-and/or rights consistent with this License. However, in accepting such
-obligations, You may act only on Your own behalf and on Your sole
-responsibility, not on behalf of any other Contributor, and only if You agree to
-indemnify, defend, and hold each Contributor harmless for any liability incurred
-by, or claims asserted against, such Contributor by reason of your accepting any
-such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-***************************************************************************
-
-%%The following software may be included in this product:
-Apache BCEL (Byte Code Engineering Library)
-
-Use of any of this software is governed by the terms of the license below:
-
-* Apache License
- * Version 2.0, January 2004
- * http://www.apache.org/licenses/
- *
- * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
- *
- * 1. Definitions.
- *
- * "License" shall mean the terms and conditions for use, reproduction,
- * and distribution as defined by Sections 1 through 9 of this document.
- *
- * "Licensor" shall mean the copyright owner or entity authorized by
- * the copyright owner that is granting the License.
- *
- * "Legal Entity" shall mean the union of the acting entity and all
- * other entities that control, are controlled by, or are under common
- * control with that entity. For the purposes of this definition,
- * "control" means (i) the power, direct or indirect, to cause the
- * direction or management of such entity, whether by contract or
- * otherwise, or (ii) ownership of fifty percent (50%) or more of the
- * outstanding shares, or (iii) beneficial ownership of such entity.
- *
- * "You" (or "Your") shall mean an individual or Legal Entity
- * exercising permissions granted by this License.
- *
- * "Source" form shall mean the preferred form for making modifications,
- * including but not limited to software source code, documentation
- * source, and configuration files.
- *
- * "Object" form shall mean any form resulting from mechanical
- * transformation or translation of a Source form, including but
- * not limited to compiled object code, generated documentation,
- * and conversions to other media types.
- *
- * "Work" shall mean the work of authorship, whether in Source or
- * Object form, made available under the License, as indicated by a
- * copyright notice that is included in or attached to the work
- * (an example is provided in the Appendix below).
- *
- * "Derivative Works" shall mean any work, whether in Source or Object
- * form, that is based on (or derived from) the Work and for which the
- * editorial revisions, annotations, elaborations, or other modifications
- * represent, as a whole, an original work of authorship. For the purposes
- * of this License, Derivative Works shall not include works that remain
- * separable from, or merely link (or bind by name) to the interfaces of,
- * the Work and Derivative Works thereof.
- *
- * "Contribution" shall mean any work of authorship, including
- * the original version of the Work and any modifications or additions
- * to that Work or Derivative Works thereof, that is intentionally
- * submitted to Licensor for inclusion in the Work by the copyright owner
- * or by an individual or Legal Entity authorized to submit on behalf of
- * the copyright owner. For the purposes of this definition, "submitted"
- * means any form of electronic, verbal, or written communication sent
- * to the Licensor or its representatives, including but not limited to
- * communication on electronic mailing lists, source code control systems,
- * and issue tracking systems that are managed by, or on behalf of, the
- * Licensor for the purpose of discussing and improving the Work, but
- * excluding communication that is conspicuously marked or otherwise
- * designated in writing by the copyright owner as "Not a Contribution."
- *
- * "Contributor" shall mean Licensor and any individual or Legal Entity
- * on behalf of whom a Contribution has been received by Licensor and
- * subsequently incorporated within the Work.
- *
- * 2. Grant of Copyright License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * copyright license to reproduce, prepare Derivative Works of,
- * publicly display, publicly perform, sublicense, and distribute the
- * Work and such Derivative Works in Source or Object form.
- *
- * 3. Grant of Patent License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * (except as stated in this section) patent license to make, have made,
- * use, offer to sell, sell, import, and otherwise transfer the Work,
- * where such license applies only to those patent claims licensable
- * by such Contributor that are necessarily infringed by their
- * Contribution(s) alone or by combination of their Contribution(s)
- * with the Work to which such Contribution(s) was submitted. If You
- * institute patent litigation against any entity (including a
- * cross-claim or counterclaim in a lawsuit) alleging that the Work
- * or a Contribution incorporated within the Work constitutes direct
- * or contributory patent infringement, then any patent licenses
- * granted to You under this License for that Work shall terminate
- * as of the date such litigation is filed.
- *
- * 4. Redistribution. You may reproduce and distribute copies of the
- * Work or Derivative Works thereof in any medium, with or without
- * modifications, and in Source or Object form, provided that You
- * meet the following conditions:
- *
- * (a) You must give any other recipients of the Work or
- * Derivative Works a copy of this License; and
- *
- * (b) You must cause any modified files to carry prominent notices
- * stating that You changed the files; and
- *
- * (c) You must retain, in the Source form of any Derivative Works
- * that You distribute, all copyright, patent, trademark, and
- * attribution notices from the Source form of the Work,
- * excluding those notices that do not pertain to any part of
- * the Derivative Works; and
- *
- * (d) If the Work includes a "NOTICE" text file as part of its
- * distribution, then any Derivative Works that You distribute must
- * include a readable copy of the attribution notices contained
- * within such NOTICE file, excluding those notices that do not
- * pertain to any part of the Derivative Works, in at least one
- * of the following places: within a NOTICE text file distributed
- * as part of the Derivative Works; within the Source form or
- * documentation, if provided along with the Derivative Works; or,
- * within a display generated by the Derivative Works, if and
- * wherever such third-party notices normally appear. The contents
- * of the NOTICE file are for informational purposes only and
- * do not modify the License. You may add Your own attribution
- * notices within Derivative Works that You distribute, alongside
- * or as an addendum to the NOTICE text from the Work, provided
- * that such additional attribution notices cannot be construed
- * as modifying the License.
- *
- * You may add Your own copyright statement to Your modifications and
- * may provide additional or different license terms and conditions
- * for use, reproduction, or distribution of Your modifications, or
- * for any such Derivative Works as a whole, provided Your use,
- * reproduction, and distribution of the Work otherwise complies with
- * the conditions stated in this License.
- *
- * 5. Submission of Contributions. Unless You explicitly state otherwise,
- * any Contribution intentionally submitted for inclusion in the Work
- * by You to the Licensor shall be under the terms and conditions of
- * this License, without any additional terms or conditions.
- * Notwithstanding the above, nothing herein shall supersede or modify
- * the terms of any separate license agreement you may have executed
- * with Licensor regarding such Contributions.
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor,
- * except as required for reasonable and customary use in describing the
- * origin of the Work and reproducing the content of the NOTICE file.
- *
- * 7. Disclaimer of Warranty. Unless required by applicable law or
- * agreed to in writing, Licensor provides the Work (and each
- * Contributor provides its Contributions) on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied, including, without limitation, any warranties or conditions
- * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- * PARTICULAR PURPOSE. You are solely responsible for determining the
- * appropriateness of using or redistributing the Work and assume any
- * risks associated with Your exercise of permissions under this License.
- *
- * 8. Limitation of Liability. In no event and under no legal theory,
- * whether in tort (including negligence), contract, or otherwise,
- * unless required by applicable law (such as deliberate and grossly
- * negligent acts) or agreed to in writing, shall any Contributor be
- * liable to You for damages, including any direct, indirect, special,
- * incidental, or consequential damages of any character arising as a
- * result of this License or out of the use or inability to use the
- * Work (including but not limited to damages for loss of goodwill,
- * work stoppage, computer failure or malfunction, or any and all
- * other commercial damages or losses), even if such Contributor
- * has been advised of the possibility of such damages.
- *
- * 9. Accepting Warranty or Additional Liability. While redistributing
- * the Work or Derivative Works thereof, You may choose to offer,
- * and charge a fee for, acceptance of support, warranty, indemnity,
- * or other liability obligations and/or rights consistent with this
- * License. However, in accepting such obligations, You may act only
- * on Your own behalf and on Your sole responsibility, not on behalf
- * of any other Contributor, and only if You agree to indemnify,
- * defend, and hold each Contributor harmless for any liability
- * incurred by, or claims asserted against, such Contributor by reason
- * of your accepting any such warranty or additional liability.
- *
- * END OF TERMS AND CONDITIONS
- *
- * APPENDIX: How to apply the Apache License to your work.
- *
- * To apply the Apache License to your work, attach the following
- * boilerplate notice, with the fields enclosed by brackets "[]"
- * replaced with your own identifying information. (Don't include
- * the brackets!) The text should be enclosed in the appropriate
- * comment syntax for the file format. We also recommend that a
- * file or class name and description of purpose be included on the
- * same "printed page" as the copyright notice for easier
- * identification within third-party archives.
- *
- * Copyright [yyyy] [name of copyright owner]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-***************************************************************************
-
-%%The following software may be included in this product:
-Jetty HTTP Server
-
-Use of any of this software is governed by the terms of the license below:
-
-Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-Additional License(s)
-
-All source files carry one of three copyrights:
-
-Copyright (c) 1999 The Apache Software Foundation. All rights reserved.
-Copyright (c) 1996 Mort Bay Consulting Pty. Ltd. All rights reserved.
-Copyright (c) 1996 Optimus Solutions Pty. Ltd. All rights reserved.
-
-One file is under the LGPL. This appears to be an oversight and it's
-in an optional "extras"
-component that we don't ship.
-
-***************************************************************************
-
-%%The following software may be included in this product:
-Apache Jakarta Commons
-
-Use of any of this software is governed by the terms of the license below:
-
-Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-***************************************************************************
-
-%%The following software may be included in this product:
-Ant
-
-Use of any of this software is governed by the terms of the license below:
-
-License
-The Apache Software License Version 2.0
-
-The Apache Software License Version 2.0 applies to all releases of Ant starting
-with ant 1.6.1
-
-/*
- * Apache License
- * Version 2.0, January 2004
- * http://www.apache.org/licenses/
- *
- * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
- *
- * 1. Definitions.
- *
- * "License" shall mean the terms and conditions for use, reproduction,
- * and distribution as defined by Sections 1 through 9 of this document.
- *
- * "Licensor" shall mean the copyright owner or entity authorized by
- * the copyright owner that is granting the License.
- *
- * "Legal Entity" shall mean the union of the acting entity and all
- * other entities that control, are controlled by, or are under common
- * control with that entity. For the purposes of this definition,
- * "control" means (i) the power, direct or indirect, to cause the
- * direction or management of such entity, whether by contract or
- * otherwise, or (ii) ownership of fifty percent (50%) or more of the
- * outstanding shares, or (iii) beneficial ownership of such entity.
- *
- * "You" (or "Your") shall mean an individual or Legal Entity
- * exercising permissions granted by this License.
- *
- * "Source" form shall mean the preferred form for making modifications,
- * including but not limited to software source code, documentation
- * source, and configuration files.
- *
- * "Object" form shall mean any form resulting from mechanical
- * transformation or translation of a Source form, including but
- * not limited to compiled object code, generated documentation,
- * and conversions to other media types.
- *
- * "Work" shall mean the work of authorship, whether in Source or
- * Object form, made available under the License, as indicated by a
- * copyright notice that is included in or attached to the work
- * (an example is provided in the Appendix below).
- *
- * "Derivative Works" shall mean any work, whether in Source or Object
- * form, that is based on (or derived from) the Work and for which the
- * editorial revisions, annotations, elaborations, or other modifications
- * represent, as a whole, an original work of authorship. For the purposes
- * of this License, Derivative Works shall not include works that remain
- * separable from, or merely link (or bind by name) to the interfaces of,
- * the Work and Derivative Works thereof.
- *
- * "Contribution" shall mean any work of authorship, including
- * the original version of the Work and any modifications or additions
- * to that Work or Derivative Works thereof, that is intentionally
- * submitted to Licensor for inclusion in the Work by the copyright owner
- * or by an individual or Legal Entity authorized to submit on behalf of
- * the copyright owner. For the purposes of this definition, "submitted"
- * means any form of electronic, verbal, or written communication sent
- * to the Licensor or its representatives, including but not limited to
- * communication on electronic mailing lists, source code control systems,
- * and issue tracking systems that are managed by, or on behalf of, the
- * Licensor for the purpose of discussing and improving the Work, but
- * excluding communication that is conspicuously marked or otherwise
- * designated in writing by the copyright owner as "Not a Contribution."
- *
- * "Contributor" shall mean Licensor and any individual or Legal Entity
- * on behalf of whom a Contribution has been received by Licensor and
- * subsequently incorporated within the Work.
- *
- * 2. Grant of Copyright License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * copyright license to reproduce, prepare Derivative Works of,
- * publicly display, publicly perform, sublicense, and distribute the
- * Work and such Derivative Works in Source or Object form.
- *
- * 3. Grant of Patent License. Subject to the terms and conditions of
- * this License, each Contributor hereby grants to You a perpetual,
- * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- * (except as stated in this section) patent license to make, have made,
- * use, offer to sell, sell, import, and otherwise transfer the Work,
- * where such license applies only to those patent claims licensable
- * by such Contributor that are necessarily infringed by their
- * Contribution(s) alone or by combination of their Contribution(s)
- * with the Work to which such Contribution(s) was submitted. If You
- * institute patent litigation against any entity (including a
- * cross-claim or counterclaim in a lawsuit) alleging that the Work
- * or a Contribution incorporated within the Work constitutes direct
- * or contributory patent infringement, then any patent licenses
- * granted to You under this License for that Work shall terminate
- * as of the date such litigation is filed.
- *
- * 4. Redistribution. You may reproduce and distribute copies of the
- * Work or Derivative Works thereof in any medium, with or without
- * modifications, and in Source or Object form, provided that You
- * meet the following conditions:
- *
- * (a) You must give any other recipients of the Work or
- * Derivative Works a copy of this License; and
- *
- * (b) You must cause any modified files to carry prominent notices
- * stating that You changed the files; and
- *
- * (c) You must retain, in the Source form of any Derivative Works
- * that You distribute, all copyright, patent, trademark, and
- * attribution notices from the Source form of the Work,
- * excluding those notices that do not pertain to any part of
- * the Derivative Works; and
- *
- * (d) If the Work includes a "NOTICE" text file as part of its
- * distribution, then any Derivative Works that You distribute must
- * include a readable copy of the attribution notices contained
- * within such NOTICE file, excluding those notices that do not
- * pertain to any part of the Derivative Works, in at least one
- * of the following places: within a NOTICE text file distributed
- * as part of the Derivative Works; within the Source form or
- * documentation, if provided along with the Derivative Works; or,
- * within a display generated by the Derivative Works, if and
- * wherever such third-party notices normally appear. The contents
- * of the NOTICE file are for informational purposes only and
- * do not modify the License. You may add Your own attribution
- * notices within Derivative Works that You distribute, alongside
- * or as an addendum to the NOTICE text from the Work, provided
- * that such additional attribution notices cannot be construed
- * as modifying the License.
- *
- * You may add Your own copyright statement to Your modifications and
- * may provide additional or different license terms and conditions
- * for use, reproduction, or distribution of Your modifications, or
- * for any such Derivative Works as a whole, provided Your use,
- * reproduction, and distribution of the Work otherwise complies with
- * the conditions stated in this License.
- *
- * 5. Submission of Contributions. Unless You explicitly state otherwise,
- * any Contribution intentionally submitted for inclusion in the Work
- * by You to the Licensor shall be under the terms and conditions of
- * this License, without any additional terms or conditions.
- * Notwithstanding the above, nothing herein shall supersede or modify
- * the terms of any separate license agreement you may have executed
- * with Licensor regarding such Contributions.
- *
- * 6. Trademarks. This License does not grant permission to use the trade
- * names, trademarks, service marks, or product names of the Licensor,
- * except as required for reasonable and customary use in describing the
- * origin of the Work and reproducing the content of the NOTICE file.
- *
- * 7. Disclaimer of Warranty. Unless required by applicable law or
- * agreed to in writing, Licensor provides the Work (and each
- * Contributor provides its Contributions) on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied, including, without limitation, any warranties or conditions
- * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- * PARTICULAR PURPOSE. You are solely responsible for determining the
- * appropriateness of using or redistributing the Work and assume any
- * risks associated with Your exercise of permissions under this License.
- *
- * 8. Limitation of Liability. In no event and under no legal theory,
- * whether in tort (including negligence), contract, or otherwise,
- * unless required by applicable law (such as deliberate and grossly
- * negligent acts) or agreed to in writing, shall any Contributor be
- * liable to You for damages, including any direct, indirect, special,
- * incidental, or consequential damages of any character arising as a
- * result of this License or out of the use or inability to use the
- * Work (including but not limited to damages for loss of goodwill,
- * work stoppage, computer failure or malfunction, or any and all
- * other commercial damages or losses), even if such Contributor
- * has been advised of the possibility of such damages.
- *
- * 9. Accepting Warranty or Additional Liability. While redistributing
- * the Work or Derivative Works thereof, You may choose to offer,
- * and charge a fee for, acceptance of support, warranty, indemnity,
- * or other liability obligations and/or rights consistent with this
- * License. However, in accepting such obligations, You may act only
- * on Your own behalf and on Your sole responsibility, not on behalf
- * of any other Contributor, and only if You agree to indemnify,
- * defend, and hold each Contributor harmless for any liability
- * incurred by, or claims asserted against, such Contributor by reason
- * of your accepting any such warranty or additional liability.
- *
- * END OF TERMS AND CONDITIONS
- *
- * APPENDIX: How to apply the Apache License to your work.
- *
- * To apply the Apache License to your work, attach the following
- * boilerplate notice, with the fields enclosed by brackets "[]"
- * replaced with your own identifying information. (Don't include
- * the brackets!) The text should be enclosed in the appropriate
- * comment syntax for the file format. We also recommend that a
- * file or class name and description of purpose be included on the
- * same "printed page" as the copyright notice for easier
- * identification within third-party archives.
- *
- * Copyright [yyyy] Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-You can download the original license file here.
-
-The License is accompanied by a NOTICE
-
- =========================================================================
- == NOTICE file corresponding to the section 4 d of ==
- == the Apache License, Version 2.0, ==
- == in this case for the Apache Ant distribution. ==
- =========================================================================
-
- This product includes software developed by
- The Apache Software Foundation (http://www.apache.org/).
-
- This product includes also software developed by :
- - the W3C consortium (http://www.w3c.org) ,
- - the SAX project (http://www.saxproject.org)
-
- Please read the different LICENSE files present in the root directory of
- this distribution.
-
- The names "Ant" and "Apache Software Foundation" must not be used to
- endorse or promote products derived from this software without prior
- written permission. For written permission, please contact
- apache@apache.org.
-
-The Apache Software License, Version 1.1
-
-The Apache Software License, Version 1.1, applies to all versions of up to ant
-1.6.0 included.
-
-/*
- * ============================================================================
- * The Apache Software License, Version 1.1
- * ============================================================================
- *
- * Copyright (C) 2000-2003 The Apache Software Foundation. All
- * rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modifica-
- * tion, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The end-user documentation included with the redistribution, if any, must
- * include the following acknowledgment: "This product includes software
- * developed by the Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself, if
- * and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Ant" and "Apache Software Foundation" must not be used to
- * endorse or promote products derived from this software without prior
- * written permission. For written permission, please contact
- * apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache", nor may
- * "Apache" appear in their name, without prior written permission of the
- * Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * This software consists of voluntary contributions made by many individuals
- * on behalf of the Apache Software Foundation. For more information on the
- * Apache Software Foundation, please see .
- *
- */
-
-
-Additional License(s)
-
-none
-
-***************************************************************************
-
-%%The following software may be included in this product:
-SAX
-
-Use of any of this software is governed by the terms of the license below:
-
-There is not a license - it is in the public domain
-
-Copyright Disclaimers
-
-This page includes statements to that effect by David Megginson, who would have
-been able to claim copyright for the original work.
-
-SAX 1.0
-
-Version 1.0 of the Simple API for XML (SAX), created collectively by the
-membership of the XML-DEV mailing list, is hereby released into the public
-domain.
-
-No one owns SAX: you may use it freely in both commercial and non-commercial
-applications, bundle it with your software distribution, include it on a CD-ROM,
-list the source code in a book, mirror the documentation at your own web site,
-or use it in any other way you see fit.
-
-SAX 2.0
-
-I hereby abandon any property rights to SAX 2.0 (the Simple API for XML), and
-release all of the SAX 2.0 source code, compiled code, and documentation
-contained in this distribution into the Public Domain. SAX comes with NO
-WARRANTY or guarantee of fitness for any purpose.
-
- David Megginson, david@megginson.com
- 2000-05-05
-
-Additional License(s)
-
-Public domain software
-
-***************************************************************************
-
-%%The following software may be included in this product:
-Ant-Contrib
-
-Use of any of this software is governed by the terms of the license below:
-
-/*
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001-2003 Ant-Contrib project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowlegement:
- * "This product includes software developed by the
- * Ant-Contrib project (http://sourceforge.net/projects/ant-contrib)."
- * Alternately, this acknowlegement may appear in the software itself,
- * if and wherever such third-party acknowlegements normally appear.
- *
- * 4. The name Ant-Contrib must not be used to endorse or promote products
- * derived from this software without prior written permission. For
- * written permission, please contact
- * ant-contrib-developers@lists.sourceforge.net.
- *
- * 5. Products derived from this software may not be called "Ant-Contrib"
- * nor may "Ant-Contrib" appear in their names without prior written
- * permission of the Ant-Contrib project.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE ANT-CONTRIB PROJECT OR ITS
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- */
-
-***************************************************************************
-
-
diff --git a/ext/java_card_kit-3_0_3/lib/api_classic.jar b/ext/java_card_kit-3_0_3/lib/api_classic.jar
deleted file mode 100644
index a7d5bb5..0000000
--- a/ext/java_card_kit-3_0_3/lib/api_classic.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/lib/api_connected.jar b/ext/java_card_kit-3_0_3/lib/api_connected.jar
deleted file mode 100644
index 14812ba..0000000
--- a/ext/java_card_kit-3_0_3/lib/api_connected.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/lib/logging.properties b/ext/java_card_kit-3_0_3/lib/logging.properties
deleted file mode 100644
index 5f34c9d..0000000
--- a/ext/java_card_kit-3_0_3/lib/logging.properties
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved.
-
-# Properties file which configures the operation of the JDK
-# logging facility.
-
-# The system will look for this config file, first using
-# a System property specified at startup:
-#
-# >java -Djava.util.logging.config.file=myLoggingConfigFilePath
-#
-# If this property is not specified, then the config file is
-# retrieved from its default location at:
-#
-# JDK_HOME/jre/lib/logging.properties
-
-# Global logging properties.
-# ------------------------------------------
-# The set of handlers to be loaded upon startup.
-# Comma-separated list of class names.
-# java.util.logging.ConsoleHandler
-handlers=com.sun.javacard.tools.util.JCConsoleHandler, java.util.logging.FileHandler
-
-# Default global logging level.
-# Loggers and Handlers may override this level
-.level=ALL
-
-# Loggers
-# ------------------------------------------
-# Loggers are usually attached to packages.
-# Here, the level for each package is specified.
-# The global level is used by default, so levels
-# specified here simply act as an override.
-#com.sun.javacard.offcardinstaller=ALL
-
-# Handlers
-# -----------------------------------------
-
-com.sun.javacard.tools.util.JCConsoleHandler.level=ALL
-com.sun.javacard.tools.util.JCConsoleHandler.formatter=com.sun.javacard.tools.util.JCToolsFormatter
-com.sun.javacard.tools.util.JCConsoleHandler.filter=com.sun.javacard.tools.util.ConsoleFilter
-
-# --- FileHandler ---
-# Override of global logging level
-java.util.logging.FileHandler.level=ALL
-
-# Naming style for the output file:
-# (The output file is placed in the directory
-# defined by the "user.home" System property.)
-java.util.logging.FileHandler.pattern=%h/java%u.log
-
-# Limiting size of output file in bytes:
-java.util.logging.FileHandler.limit=50000
-
-# Number of output files to cycle through, by appending an
-# integer to the base file name:
-java.util.logging.FileHandler.count=10
-
-# Style of output (Simple or XML):
-java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
-
-java.util.logging.FileHandler.append=true
-
-#--------------print class method info
-printCurrentClassAndMethod = false
diff --git a/ext/java_card_kit-3_0_3/lib/tools.jar b/ext/java_card_kit-3_0_3/lib/tools.jar
deleted file mode 100644
index f5c9b23..0000000
--- a/ext/java_card_kit-3_0_3/lib/tools.jar
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/shared/Java_clr_hori.gif b/ext/java_card_kit-3_0_3/shared/Java_clr_hori.gif
deleted file mode 100644
index 10eab90..0000000
--- a/ext/java_card_kit-3_0_3/shared/Java_clr_hori.gif
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/shared/Java_clr_hori_interval.gif b/ext/java_card_kit-3_0_3/shared/Java_clr_hori_interval.gif
deleted file mode 100644
index 3230819..0000000
--- a/ext/java_card_kit-3_0_3/shared/Java_clr_hori_interval.gif
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/shared/Java_clr_hori_small.gif b/ext/java_card_kit-3_0_3/shared/Java_clr_hori_small.gif
deleted file mode 100644
index fdb9030..0000000
--- a/ext/java_card_kit-3_0_3/shared/Java_clr_hori_small.gif
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/shared/downicon.gif b/ext/java_card_kit-3_0_3/shared/downicon.gif
deleted file mode 100644
index d178dd6..0000000
--- a/ext/java_card_kit-3_0_3/shared/downicon.gif
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/shared/oracle.gif b/ext/java_card_kit-3_0_3/shared/oracle.gif
deleted file mode 100644
index 4a98827..0000000
--- a/ext/java_card_kit-3_0_3/shared/oracle.gif
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/shared/smallOracleLogo.gif b/ext/java_card_kit-3_0_3/shared/smallOracleLogo.gif
deleted file mode 100644
index d06d49d..0000000
--- a/ext/java_card_kit-3_0_3/shared/smallOracleLogo.gif
+++ /dev/null
Binary files differ
diff --git a/ext/java_card_kit-3_0_3/shared/topicon.gif b/ext/java_card_kit-3_0_3/shared/topicon.gif
deleted file mode 100644
index f4dfbf3..0000000
--- a/ext/java_card_kit-3_0_3/shared/topicon.gif
+++ /dev/null
Binary files differ
diff --git a/ext/libs b/ext/libs
new file mode 160000
+Subproject e1928e81c279c6996c31703e8853e19cb16d76d
diff --git a/ext/mscng b/ext/mscng
new file mode 160000
+Subproject 084ce2130403188ffd01aa04e44fea87b03236d
diff --git a/ext/sdks b/ext/sdks
new file mode 160000
+Subproject 4a696701af819af40a3678a3734d8e704a09f4b
diff --git a/ext/visa_openplatform-2_0/visa/openplatform/javacard/openplatform.exp b/ext/visa_openplatform-2_0/visa/openplatform/javacard/openplatform.exp
deleted file mode 100644
index b889504..0000000
--- a/ext/visa_openplatform-2_0/visa/openplatform/javacard/openplatform.exp
+++ /dev/null
Binary files differ
diff --git a/ext/visa_openplatform-2_0/visaop20.jar b/ext/visa_openplatform-2_0/visaop20.jar
deleted file mode 100644
index c1fe3b8..0000000
--- a/ext/visa_openplatform-2_0/visaop20.jar
+++ /dev/null
Binary files differ
diff --git a/lib/commons-cli-1.3.1-javadoc.jar b/lib/commons-cli-1.3.1-javadoc.jar
deleted file mode 100644
index c741ec4..0000000
--- a/lib/commons-cli-1.3.1-javadoc.jar
+++ /dev/null
Binary files differ
diff --git a/lib/commons-cli-1.3.1.jar b/lib/commons-cli-1.3.1.jar
deleted file mode 100644
index c3e7a1f..0000000
--- a/lib/commons-cli-1.3.1.jar
+++ /dev/null
Binary files differ
diff --git a/lib/commons-cli-1.4-javadoc.jar b/lib/commons-cli-1.4-javadoc.jar
new file mode 100644
index 0000000..6b21f98
--- /dev/null
+++ b/lib/commons-cli-1.4-javadoc.jar
Binary files differ
diff --git a/lib/commons-cli-1.4.jar b/lib/commons-cli-1.4.jar
new file mode 100644
index 0000000..22deb30
--- /dev/null
+++ b/lib/commons-cli-1.4.jar
Binary files differ
diff --git a/nbproject/dist-build.xml b/nbproject/dist-build.xml
index b980e2d..b1bfadf 100644
--- a/nbproject/dist-build.xml
+++ b/nbproject/dist-build.xml
@@ -10,22 +10,27 @@
<tempfile property="temp.file" destDir="${java.io.tmpdir}" suffix=".jar"/>
<tempfile property="temp.previous_jar" destdir="${java.io.tmpdir}" suffix=".jar"/>
+ <exec executable="git" outputproperty="git.commit" failifexecutionfails="false">
+ <arg line="rev-parse --short HEAD"/>
+ </exec>
+
<copy file="${store.jar}" tofile="${temp.previous_jar}" failonerror="false"/>
<echo message="Backed up ${store.jar} into ${temp.previous_jar}"/>
<delete file="${store.jar}" failonerror="false"/>
- <jar destfile="${temp.file}" filesetmanifest="skip">
+ <jar destfile="${temp.file}" filesetmanifest="skip" compress="true" level="8">
<zipgroupfileset dir="dist" includes="*.jar"/>
<zipgroupfileset dir="dist/lib" includes="*.jar"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
+ <attribute name="Git-Commit" value="${git.commit}"/>
</manifest>
</jar>
- <zip destfile="${store.jar}">
+ <zip destfile="${store.jar}" compress="true" level="8">
<zipfileset src="${temp.file}"
- excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
+ excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA, ${dist.archive.excludes}"/>
</zip>
<delete file="${temp.file}"/>
diff --git a/nbproject/keystore b/nbproject/keystore
new file mode 100755
index 0000000..7c9c8e4
--- /dev/null
+++ b/nbproject/keystore
Binary files differ
diff --git a/nbproject/reader/manifest.mf b/nbproject/reader/manifest.mf
index cbfea93..c2a00ee 100644
--- a/nbproject/reader/manifest.mf
+++ b/nbproject/reader/manifest.mf
@@ -1,4 +1,4 @@
Manifest-Version: 1.0
-Class-Path: lib/jcardsim-3.0.4-SNAPSHOT.jar lib/commons-cli-1.3.1.jar lib/snakeyaml-1.19.jar
+Class-Path: lib/jcardsim-3.0.4-SNAPSHOT.jar lib/commons-cli-1.4.jar lib/snakeyaml-1.19.jar
Main-Class: cz.crcs.ectester.reader.ECTesterReader
diff --git a/nbproject/reader/project.properties b/nbproject/reader/project.properties
index 69db523..8e11520 100644
--- a/nbproject/reader/project.properties
+++ b/nbproject/reader/project.properties
@@ -6,7 +6,7 @@ annotation.processing.source.output=${build.generated.sources.dir}/ap-source-out
application.title=ECTesterReader
application.vendor=xsvenda
build.classes.dir=${build.dir}/classes
-build.classes.excludes=**/*.java,**/*.form,**/*.c,**/*.h,**/*.a,**/*.o,**/Makefile
+build.classes.excludes=**/*.java,**/*.form,**/*.c,**/*.cpp,**/*.hpp,**/*.h,**/*.a,**/*.o,**/Makefile
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
@@ -31,14 +31,14 @@ libs.CopyLibs.classpath=nbproject/copylibstask.jar
endorsed.classpath=
excludes=
includes=**/applet/**,**/common/**,**/data/**,**/reader/**
-jar.compress=false
+jar.compress=true
javac.classpath=\
lib/bcprov-jdk15on-1.58.jar:\
lib/jcardsim-3.0.4-SNAPSHOT.jar:\
- lib/commons-cli-1.3.1.jar:\
+ lib/commons-cli-1.4.jar:\
lib/snakeyaml-1.19.jar
# Space-separated list of extra javac options
-javac.compilerargs=
+javac.compilerargs=-Xlint:all
javac.deprecation=false
javac.processorpath=\
${javac.classpath}
diff --git a/nbproject/standalone/manifest.mf b/nbproject/standalone/manifest.mf
index 02f1e3e..5e8f5d9 100644
--- a/nbproject/standalone/manifest.mf
+++ b/nbproject/standalone/manifest.mf
@@ -1,4 +1,4 @@
Manifest-Version: 1.0
-Class-Path: lib/bcprov-jdk15on-1.58.jar lib/jcardsim-3.0.4-SNAPSHOT.jar lib/commons-cli-1.3.1.jar lib/snakeyaml-1.19.jar
+Class-Path: lib/bcprov-jdk15on-1.58.jar lib/jcardsim-3.0.4-SNAPSHOT.jar lib/commons-cli-1.4.jar lib/snakeyaml-1.19.jar
Main-Class: cz.crcs.ectester.standalone.ECTesterStandalone
diff --git a/nbproject/standalone/project.properties b/nbproject/standalone/project.properties
index 9fed4c2..7ad08a1 100644
--- a/nbproject/standalone/project.properties
+++ b/nbproject/standalone/project.properties
@@ -6,7 +6,7 @@ annotation.processing.source.output=${build.generated.sources.dir}/ap-source-out
application.title=ECTesterStandalone
application.vendor=xsvenda
build.classes.dir=${build.dir}/classes
-build.classes.excludes=**/*.java,**/*.form,**/*.c,**/*.h,**/*.a,**/*.o,**/Makefile
+build.classes.excludes=**/*.java,**/*.form,**/*.c,**/*.cpp,**/*.hpp,**/*.h,**/*.a,**/*.o,**/Makefile
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
@@ -22,7 +22,7 @@ debug.classpath=\
debug.test.classpath=\
${run.test.classpath}
# Files in build.classes.dir which should be excluded from distribution jar
-dist.archive.excludes=
+dist.archive.excludes=**/*.java,**/*.form,**/*.c,**/*.cpp,**/*.hpp,**/*.h,**/*.a,**/*.o,**/Makefile
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/ECTesterStandalone.jar
@@ -31,14 +31,14 @@ libs.CopyLibs.classpath=nbproject/copylibstask.jar
endorsed.classpath=
excludes=
includes=**/common/**,**/standalone/**,**/data/**,**/applet/*
-jar.compress=false
+jar.compress=true
javac.classpath=\
lib/bcprov-jdk15on-1.58.jar:\
lib/jcardsim-3.0.4-SNAPSHOT.jar:\
- lib/commons-cli-1.3.1.jar:\
+ lib/commons-cli-1.4.jar:\
lib/snakeyaml-1.19.jar
# Space-separated list of extra javac options
-javac.compilerargs=
+javac.compilerargs=-Xlint:all
javac.deprecation=false
javac.processorpath=\
${javac.classpath}
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;
+ }
}
diff --git a/util/plot_dh.py b/util/plot_dh.py
index 2354688..468e73a 100755
--- a/util/plot_dh.py
+++ b/util/plot_dh.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
#
# Script for plotting ECTester ECDH results.
@@ -13,14 +13,16 @@
import numpy as np
import matplotlib.pyplot as plt
-import matplotlib.ticker as ticker
+from matplotlib import ticker, colors
import argparse
+from copy import deepcopy
from operator import itemgetter
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Plot ECTester ECDH timing.")
parser.add_argument("-o", "--output", dest="output", type=argparse.FileType("wb"), help="Write image to [file], do not display.", metavar="file")
parser.add_argument("--skip-first", dest="skip_first", action="store_true", help="Skip first entry, as it's usually a large outlier.")
+ parser.add_argument("-t", "--title", dest="title", nargs="?", default="", type=str, help="What title to give the figure.")
parser.add_argument("file", type=str, help="The file to plot(csv).")
opts = parser.parse_args()
@@ -36,23 +38,31 @@ if __name__ == "__main__":
if "nano" in header_names[1]:
unit = r"$\mu s$"
- time_data = map(lambda x: x[1]/1000, data)
+ time_data = map(lambda x: x[1]//1000, data)
else:
unit = r"ms"
time_data = map(itemgetter(1), data)
- priv_data = map(itemgetter(2), data)
- pub_data = map(itemgetter(3), data)
- secret_data = map(itemgetter(4), data)
+ time_data = list(time_data)
+ priv_data = list(map(itemgetter(2), data))
+ pub_data = list(map(itemgetter(3), data))
+ secret_data = list(map(itemgetter(4), data))
plt.style.use("ggplot")
- fig = plt.figure(tight_layout=True)
- fig.suptitle(opts.file)
+ fig = plt.figure()
+ layout_kwargs = {}
+ if opts.title is None:
+ fig.suptitle(opts.file)
+ layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
+ elif opts.title:
+ fig.suptitle(opts.title)
+ layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
+ fig.tight_layout(**layout_kwargs)
- axe_hist = fig.add_subplot(1,1,1)
+ axe_hist = fig.add_subplot(2,1,1)
time_max = max(time_data)
time_avg = np.average(time_data)
time_median = np.median(time_data)
- axe_hist.hist(time_data, bins=time_max/3, log=True)
+ axe_hist.hist(time_data, bins=time_max//3, log=True)
axe_hist.axvline(x=time_avg, alpha=0.7, linestyle="dotted", color="red", label="avg = {}".format(time_avg))
axe_hist.axvline(x=time_median, alpha=0.7, linestyle="dotted", color="green", label="median = {}".format(time_median))
axe_hist.set_ylabel("count\n(log)")
@@ -60,10 +70,38 @@ if __name__ == "__main__":
axe_hist.xaxis.set_major_locator(ticker.MaxNLocator())
axe_hist.legend(loc="best")
+ priv_bit_bins = {}
+ for i in range(len(data)):
+ skey = priv_data[i]
+ time = time_data[i]
+ skey_hw = 0
+ while skey:
+ skey_hw += 1
+ skey &= skey - 1
+ if skey_hw in priv_bit_bins:
+ priv_bit_bins[skey_hw].append(time)
+ else:
+ priv_bit_bins[skey_hw] = [time]
+ priv_bit_x = []
+ priv_bit_y = []
+ for k,v in priv_bit_bins.items():
+ priv_bit_x.extend([k] * len(v))
+ priv_bit_y.extend(v)
+
+ axe_priv_hist = fig.add_subplot(2,1,2)
+ h, xe, ye = np.histogram2d(priv_bit_x, priv_bit_y, bins=[max(priv_bit_bins) - min(priv_bit_bins), (time_max - min(time_data))//5])
+ cmap = deepcopy(plt.cm.plasma)
+ cmap.set_bad("black")
+ im = axe_priv_hist.imshow(h.T, origin="low", cmap=cmap, aspect="auto", extent=[xe[0], xe[-1], ye[0], ye[-1]], norm=colors.LogNorm())
+ axe_priv_hist.set_xlabel("private key Hamming weight")
+ axe_priv_hist.set_ylabel("time ({})".format(unit))
+ fig.colorbar(im, ax=axe_priv_hist)
+
fig.text(0.01, 0.02, "Data size: {}".format(len(time_data)), size="small")
if opts.output is None:
plt.show()
else:
fig.set_size_inches(12, 10)
- plt.savefig(opts.output, dpi=400)
+ ext = opts.output.name.split(".")[-1]
+ plt.savefig(opts.output, format=ext, dpi=400, bbox_inches='tight')
diff --git a/util/plot_gen.py b/util/plot_gen.py
index 12f7089..98d8261 100755
--- a/util/plot_gen.py
+++ b/util/plot_gen.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
#
# Script for plotting ECTester key generation results.
@@ -14,7 +14,9 @@
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
+import matplotlib.colors as colors
from operator import itemgetter
+from copy import deepcopy
import argparse
if __name__ == "__main__":
@@ -23,7 +25,9 @@ if __name__ == "__main__":
parser.add_argument("--pub", dest="pub", action="store_true", help="Show public key scatter plot.")
parser.add_argument("--priv", dest="priv", action="store_true", help="Show private key scatter plot.")
parser.add_argument("--hist", dest="hist", action="store_true", help="Show histogram.")
+ parser.add_argument("--hw-hist", dest="hw_hist", action="store_true", help="Show Hamming weight 2D histogram (private key Hamming weight and generation time).")
parser.add_argument("--skip-first", dest="skip_first", action="store_true", help="Skip first entry, as it's usually a large outlier.")
+ parser.add_argument("-t", "--title", dest="title", type=str, nargs="?", default="", help="What title to give the figure.")
parser.add_argument("file", type=str, help="The file to plot(csv).")
opts = parser.parse_args()
@@ -32,11 +36,11 @@ if __name__ == "__main__":
header = f.readline()
header_names = header.split(";")
- plots = [opts.priv, opts.pub, opts.hist]
+ plots = [opts.priv, opts.pub, opts.hist, opts.hw_hist]
n_plots = sum(plots)
if n_plots == 0:
- n_plots = 3
- plots = [True, True, True]
+ n_plots = 4
+ plots = [True, True, True, True]
hx = lambda x: int(x, 16)
data = np.genfromtxt(opts.file, delimiter=";", skip_header=1, converters={2: hx, 3: hx}, dtype=np.dtype([("index","u4"), ("time","u4"), ("pub", "O"), ("priv", "O")]))
@@ -45,16 +49,24 @@ if __name__ == "__main__":
if "nano" in header_names[1]:
unit = r"$\mu s$"
- time_data = map(lambda x: x[1]/1000, data)
+ time_data = map(lambda x: x[1]//1000, data)
else:
unit = r"ms"
time_data = map(itemgetter(1), data)
- priv_data = map(itemgetter(2), data)
- pub_data = map(itemgetter(3), data)
+ time_data = list(time_data)
+ priv_data = list(map(itemgetter(2), data))
+ pub_data = list(map(itemgetter(3), data))
plt.style.use("ggplot")
- fig = plt.figure(tight_layout=True)
- fig.suptitle(opts.file)
+ fig = plt.figure()
+ layout_kwargs = {}
+ if opts.title is None:
+ fig.suptitle(opts.file)
+ layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
+ elif opts.title:
+ fig.suptitle(opts.title)
+ layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
+ fig.tight_layout(**layout_kwargs)
plot_i = 1
if plots[0]:
@@ -76,18 +88,48 @@ if __name__ == "__main__":
time_max = max(time_data)
time_avg = np.average(time_data)
time_median = np.median(time_data)
- axe_hist.hist(time_data, bins=time_max/3, log=True)
+ axe_hist.hist(time_data, bins=time_max//3, log=True)
axe_hist.axvline(x=time_avg, alpha=0.7, linestyle="dotted", color="red", label="avg = {}".format(time_avg))
axe_hist.axvline(x=time_median, alpha=0.7, linestyle="dotted", color="green", label="median = {}".format(time_median))
axe_hist.set_ylabel("count\n(log)")
axe_hist.set_xlabel("time ({})".format(unit))
axe_hist.xaxis.set_major_locator(ticker.MaxNLocator())
axe_hist.legend(loc="best")
+ plot_i += 1
+
+ if plots[3]:
+ priv_bit_bins = {}
+ for i in range(len(data)):
+ skey = priv_data[i]
+ time = time_data[i]
+ skey_hw = 0
+ while skey:
+ skey_hw += 1
+ skey &= skey - 1
+ if skey_hw in priv_bit_bins:
+ priv_bit_bins[skey_hw].append(time)
+ else:
+ priv_bit_bins[skey_hw] = [time]
+ priv_bit_x = []
+ priv_bit_y = []
+ for k,v in priv_bit_bins.items():
+ priv_bit_x.extend([k] * len(v))
+ priv_bit_y.extend(v)
+ axe_priv_hist = fig.add_subplot(n_plots, 1, plot_i)
+ h, xe, ye = np.histogram2d(priv_bit_x, priv_bit_y, bins=[max(priv_bit_bins) - min(priv_bit_bins), (max(time_data) - min(time_data))//5])
+ cmap = deepcopy(plt.cm.plasma)
+ cmap.set_bad("black")
+ im = axe_priv_hist.imshow(h.T, origin="low", cmap=cmap, aspect="auto", extent=[xe[0], xe[-1], ye[0], ye[-1]], norm=colors.LogNorm())
+ axe_priv_hist.set_xlabel("private key Hamming weight")
+ axe_priv_hist.set_ylabel("time ({})".format(unit))
+ fig.colorbar(im, ax=axe_priv_hist)
- fig.text(0.01, 0.02, "Data size: {}".format(len(time_data)), size="small")
+ if plot_i > 2:
+ fig.text(0.01, 0.02, "Data size: {}".format(len(time_data)), size="small")
if opts.output is None:
plt.show()
else:
fig.set_size_inches(12, 10)
- plt.savefig(opts.output, dpi=400)
+ ext = opts.output.name.split(".")[-1]
+ plt.savefig(opts.output, format=ext, dpi=400, bbox_inches='tight')